SqlQueryManager ve ListFormWizard düzenlemeleri

This commit is contained in:
Sedat Öztürk 2026-05-01 13:20:40 +03:00
parent f3a922a5a8
commit 7bb154c936
6 changed files with 190 additions and 113 deletions

View file

@ -28,10 +28,7 @@ public class ListFormWizardAppService(
IRepository<PermissionDefinitionRecord, Guid> repoPerm,
IRepository<PermissionGroupDefinitionRecord, Guid> repoPermGroup,
IRepository<Menu, Guid> repoMenu,
IIdentityRoleRepository roleRepository,
IIdentityUserRepository userRepository,
IPermissionGrantRepository permissionGrantRepository,
ILookupNormalizer LookupNormalizer,
IConfiguration configuration,
LanguageTextAppService languageTextAppService
) : PlatformAppService(), IListFormWizardAppService
@ -44,10 +41,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 IIdentityRoleRepository roleRepository = roleRepository;
private readonly IIdentityUserRepository userRepository = userRepository;
private readonly IPermissionGrantRepository permissionGrantRepository = permissionGrantRepository;
private readonly ILookupNormalizer lookupNormalizer = LookupNormalizer;
private readonly IConfiguration _configuration = configuration;
private readonly LanguageTextAppService _languageTextAppService = languageTextAppService;
private readonly string cultureNameDefault = PlatformConsts.DefaultLanguage;
@ -101,21 +95,23 @@ public class ListFormWizardAppService(
var permNote = existingPerms.FirstOrDefault(a => a.Name == WizardConsts.PermNote(wizardName)) ??
await repoPerm.InsertAsync(new PermissionDefinitionRecord(Guid.NewGuid(), groupName, WizardConsts.PermNote(wizardName), permRead.Name, WizardConsts.LangKeyNote, true, MultiTenancySides.Both), autoSave: false);
// Permission Grants - Bulk Insert
var adminUserName = PlatformConsts.AbpIdentity.User.AdminEmailDefaultValue;
var adminUser = await userRepository.FindByNormalizedUserNameAsync(lookupNormalizer.NormalizeName(adminUserName));
var adminRole = await roleRepository.FindByNormalizedNameAsync(lookupNormalizer.NormalizeName(PlatformConsts.AbpIdentity.User.AdminRoleName));
// Permission Grants - Bulk Insert (only missing ones)
var existingGrants = await permissionGrantRepository.GetListAsync("R", PlatformConsts.AbpIdentity.User.AdminRoleName);
var existingGrantNames = existingGrants.Select(g => g.Name).ToHashSet();
await permissionGrantRepository.InsertManyAsync(
[
new PermissionGrant(Guid.NewGuid(), permRead.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
new PermissionGrant(Guid.NewGuid(), permCreate.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
new PermissionGrant(Guid.NewGuid(), permUpdate.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
new PermissionGrant(Guid.NewGuid(), permDelete.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
new PermissionGrant(Guid.NewGuid(), permExport.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
new PermissionGrant(Guid.NewGuid(), permImport.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
new PermissionGrant(Guid.NewGuid(), permNote.Name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName),
], autoSave: false);
var grantsToInsert = new[]
{
permRead.Name, permCreate.Name, permUpdate.Name,
permDelete.Name, permExport.Name, permImport.Name, permNote.Name
}
.Where(name => !existingGrantNames.Contains(name))
.Select(name => new PermissionGrant(Guid.NewGuid(), name, "R", PlatformConsts.AbpIdentity.User.AdminRoleName))
.ToList();
if (grantsToInsert.Count > 0)
{
await permissionGrantRepository.InsertManyAsync(grantsToInsert, autoSave: false);
}
//Menu Parent
var menuQueryable = await repoMenu.GetQueryableAsync();
@ -185,44 +181,68 @@ public class ListFormWizardAppService(
})
.ToList();
//ListForm
var listForm = await repoListForm.InsertAsync(new ListForm
//ListForm - varsa sil, yeniden ekle
var listFormQueryable = await repoListForm.GetQueryableAsync();
var existingListForm = await AsyncExecuter.FirstOrDefaultAsync(listFormQueryable.Where(a => a.ListFormCode == input.ListFormCode));
var listFormFieldQueryable = await repoListFormField.GetQueryableAsync();
var existingListFormFields = await AsyncExecuter.ToListAsync(
listFormFieldQueryable.Where(a => a.ListFormCode == input.ListFormCode));
if (existingListFormFields.Count > 0)
{
ListFormType = ListFormTypeEnum.List,
PageSize = 10,
ExportJson = WizardConsts.DefaultExportJson,
IsSubForm = false,
ShowNote = true,
LayoutJson = WizardConsts.DefaultLayoutJson(),
CultureName = LanguageCodes.En,
ListFormCode = input.ListFormCode,
Name = nameLangKey,
Title = titleLangKey,
Description = descLangKey,
DataSourceCode = input.DataSourceCode,
IsTenant = input.IsTenant,
IsBranch = input.IsBranch,
IsOrganizationUnit = input.IsOrganizationUnit,
SelectCommandType = input.SelectCommandType,
SelectCommand = input.SelectCommand,
KeyFieldName = input.KeyFieldName,
KeyFieldDbSourceType = input.KeyFieldDbSourceType,
DefaultFilter = WizardConsts.DefaultFilterJson,
SortMode = GridOptions.SortModeSingle,
FilterRowJson = WizardConsts.DefaultFilterRowJson,
HeaderFilterJson = WizardConsts.DefaultHeaderFilterJson,
SearchPanelJson = WizardConsts.DefaultSearchPanelJson,
GroupPanelJson = JsonSerializer.Serialize(new { Visible = false }),
SelectionJson = WizardConsts.DefaultSelectionSingleJson,
ColumnOptionJson = WizardConsts.DefaultColumnOptionJson(),
PermissionJson = WizardConsts.DefaultPermissionJson(code),
DeleteCommand = WizardConsts.DefaultDeleteCommand(input.SelectCommand),
DeleteFieldsDefaultValueJson = WizardConsts.DefaultDeleteFieldsDefaultValueJson(input.KeyFieldDbSourceType),
InsertFieldsDefaultValueJson = WizardConsts.DefaultInsertFieldsDefaultValueJson(input.KeyFieldDbSourceType),
PagerOptionJson = WizardConsts.DefaultPagerOptionJson,
EditingOptionJson = WizardConsts.DefaultEditingOptionJson(titleLangKey, 600, 500, input.AllowDeleting, input.AllowAdding, input.AllowUpdating, input.ConfirmDelete, false, input.AllowDetail),
EditingFormJson = editingFormDtos.Count > 0 ? JsonSerializer.Serialize(editingFormDtos) : null,
}, autoSave: true);
await repoListFormField.DeleteManyAsync(existingListFormFields, autoSave: true);
}
void ApplyListFormValues(ListForm lf)
{
lf.ListFormType = ListFormTypeEnum.List;
lf.PageSize = 10;
lf.ExportJson = WizardConsts.DefaultExportJson;
lf.IsSubForm = false;
lf.ShowNote = true;
lf.LayoutJson = WizardConsts.DefaultLayoutJson();
lf.CultureName = LanguageCodes.En;
lf.ListFormCode = input.ListFormCode;
lf.Name = nameLangKey;
lf.Title = titleLangKey;
lf.Description = descLangKey;
lf.DataSourceCode = input.DataSourceCode;
lf.IsTenant = input.IsTenant;
lf.IsBranch = input.IsBranch;
lf.IsOrganizationUnit = input.IsOrganizationUnit;
lf.SelectCommandType = input.SelectCommandType;
lf.SelectCommand = input.SelectCommand;
lf.KeyFieldName = input.KeyFieldName;
lf.KeyFieldDbSourceType = input.KeyFieldDbSourceType;
lf.DefaultFilter = WizardConsts.DefaultFilterJson;
lf.SortMode = GridOptions.SortModeSingle;
lf.FilterRowJson = WizardConsts.DefaultFilterRowJson;
lf.HeaderFilterJson = WizardConsts.DefaultHeaderFilterJson;
lf.SearchPanelJson = WizardConsts.DefaultSearchPanelJson;
lf.GroupPanelJson = JsonSerializer.Serialize(new { Visible = false });
lf.SelectionJson = WizardConsts.DefaultSelectionSingleJson;
lf.ColumnOptionJson = WizardConsts.DefaultColumnOptionJson();
lf.PermissionJson = WizardConsts.DefaultPermissionJson(code);
lf.DeleteCommand = WizardConsts.DefaultDeleteCommand(input.SelectCommand);
lf.DeleteFieldsDefaultValueJson = WizardConsts.DefaultDeleteFieldsDefaultValueJson(input.KeyFieldDbSourceType);
lf.InsertFieldsDefaultValueJson = WizardConsts.DefaultInsertFieldsDefaultValueJson(input.KeyFieldDbSourceType);
lf.PagerOptionJson = WizardConsts.DefaultPagerOptionJson;
lf.EditingOptionJson = WizardConsts.DefaultEditingOptionJson(titleLangKey, 600, 500, input.AllowDeleting, input.AllowAdding, input.AllowUpdating, input.ConfirmDelete, false, input.AllowDetail);
lf.EditingFormJson = editingFormDtos.Count > 0 ? JsonSerializer.Serialize(editingFormDtos) : null;
}
ListForm listForm;
if (existingListForm != null)
{
ApplyListFormValues(existingListForm);
listForm = await repoListForm.UpdateAsync(existingListForm, autoSave: true);
}
else
{
var newListForm = new ListForm();
ApplyListFormValues(newListForm);
listForm = await repoListForm.InsertAsync(newListForm, autoSave: true);
}
// ListFormField - each item in each group becomes a visible field record
var fieldOrder = 0;

View file

@ -203,6 +203,11 @@ public class ListFormSeeder_Administration : IDataSeedContributor, ITransientDep
HeaderFilterJson = DefaultHeaderFilterJson,
SearchPanelJson = DefaultSearchPanelJson,
GroupPanelJson = DefaultGroupPanelJson,
SelectionJson = JsonSerializer.Serialize(new SelectionDto
{
Mode = GridOptions.SelectionAllModeAllPages,
AllowSelectAll = true
}),
ColumnOptionJson = DefaultColumnOptionJson(),
PermissionJson = DefaultPermissionJson(AbpIdentity.Permissions.Create, listFormName, AbpIdentity.Permissions.Update, AbpIdentity.Permissions.Delete, AbpIdentity.Permissions.Export, AbpIdentity.Permissions.Import, AbpIdentity.Permissions.Note),
PagerOptionJson = DefaultPagerOptionJson,

View file

@ -50,3 +50,27 @@ WITH INIT;'
EXEC sp_executesql @SQL;
END
GO
IF OBJECT_ID(N'[dbo].[Adm_T_Deparment]', 'U') IS NULL
BEGIN
CREATE TABLE [dbo].[Adm_T_Deparment]
(
[Id] uniqueidentifier NOT NULL DEFAULT NEWID(),
[CreationTime] datetime2 NOT NULL DEFAULT GETUTCDATE(),
[CreatorId] uniqueidentifier NULL,
[LastModificationTime] datetime2 NULL,
[LastModifierId] uniqueidentifier NULL,
[IsDeleted] bit NOT NULL DEFAULT 0,
[DeletionTime] datetime2 NULL,
[DeleterId] uniqueidentifier NULL,
[TenantId] uniqueidentifier NULL,
[BranchId] uniqueidentifier NOT NULL,
[Name] nvarchar(64) NOT NULL,
[ParentId] uniqueidentifier NULL,
CONSTRAINT [PK_Adm_T_Deparment] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]
END
GO

View file

@ -166,6 +166,10 @@ const Wizard = () => {
const selectableColumns = cols.filter((c) => !isAuditColumn(c.columnName))
setSelectedColumns(new Set(selectableColumns.map((c) => c.columnName)))
setEditingGroups([])
// Auto-check isTenant / isBranch based on column presence
const colNames = new Set(cols.map((c) => c.columnName.toLowerCase()))
formikRef.current?.setFieldValue('isTenant', colNames.has('tenantid'))
formikRef.current?.setFieldValue('isBranch', colNames.has('branchid'))
// Auto-select first column as key field
if (cols.length > 0) {
const first = cols[0]

View file

@ -185,10 +185,9 @@ pk AS
SELECT
' CONSTRAINT ' + QUOTENAME(k.name) + ' PRIMARY KEY ' +
CASE WHEN i.type = 1 THEN 'CLUSTERED' ELSE 'NONCLUSTERED' END +
' (' +
STUFF(
CHAR(13) + CHAR(10) + ' (' + CHAR(13) + CHAR(10) +
(
SELECT ', ' + QUOTENAME(c.name) + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END
SELECT ' ' + QUOTENAME(c.name) + CASE WHEN ic.is_descending_key = 1 THEN ' DESC' ELSE ' ASC' END + CHAR(13) + CHAR(10)
FROM sys.index_columns ic
INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id
WHERE ic.object_id = i.object_id
@ -196,16 +195,18 @@ pk AS
AND ic.is_included_column = 0
ORDER BY ic.key_ordinal
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,2,'') + ')' AS line
).value('.', 'NVARCHAR(MAX)') +
' )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]' AS line
FROM sys.key_constraints k
INNER JOIN sys.indexes i ON k.parent_object_id = i.object_id AND k.unique_index_id = i.index_id
WHERE k.parent_object_id = @ObjectId
AND k.type = 'PK'
)
SELECT
'CREATE TABLE ${fullName}' + CHAR(13) + CHAR(10) +
'(' + CHAR(13) + CHAR(10) +
'IF OBJECT_ID(N''${escapedFullName}'', ''U'') IS NULL' + CHAR(13) + CHAR(10) +
'BEGIN' + CHAR(13) + CHAR(10) +
' CREATE TABLE ${fullName}' + CHAR(13) + CHAR(10) +
' (' + CHAR(13) + CHAR(10) +
STUFF(
(
SELECT ',' + CHAR(13) + CHAR(10) + line
@ -220,7 +221,7 @@ SELECT
FROM pk
),
''
) + CHAR(13) + CHAR(10) + ');' AS Script;`
) + CHAR(13) + CHAR(10) + ' ) ON [PRIMARY]' + CHAR(13) + CHAR(10) + 'END' + CHAR(13) + CHAR(10) + 'GO' AS Script;`
}
const getTableCreateScript = async (schemaName: string, tableName: string): Promise<string> => {

View file

@ -256,10 +256,57 @@ function generateCreateTableSql(
): string {
const tableName = settings.tableName || 'NewTable'
const fullTableName = `[dbo].[${tableName}]`
const escapedFullTableName = fullTableName.replace(/'/g, "''")
const userCols = columns.filter((c) => c.columnName.trim())
const allBodyCols = userCols
const bodyLines = allBodyCols.map((c, i) => colToSqlLine(c, i < allBodyCols.length - 1))
const bodyLines = userCols.map((c) => colToSqlLine(c, false))
// Inline PRIMARY KEY constraint inside CREATE TABLE
const pkIndex = indexes.find((idx) => idx.indexType === 'PrimaryKey' && idx.columns.length > 0)
const pkConstraintLines: string[] = []
if (pkIndex) {
const clustered = pkIndex.isClustered ? 'CLUSTERED' : 'NONCLUSTERED'
const colsSql = pkIndex.columns.map((c) => ` [${c.columnName}] ${c.order}`).join(',\n')
pkConstraintLines.push(
` CONSTRAINT [${pkIndex.indexName}] PRIMARY KEY ${clustered}`,
` (`,
colsSql,
` )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON, OPTIMIZE_FOR_SEQUENTIAL_KEY = OFF) ON [PRIMARY]`,
)
}
// Build all column + pk lines with commas
const allInnerLines: string[] = []
for (let i = 0; i < bodyLines.length; i++) {
allInnerLines.push(bodyLines[i] + ',')
}
if (pkConstraintLines.length > 0) {
for (let i = 0; i < pkConstraintLines.length; i++) {
allInnerLines.push(pkConstraintLines[i])
}
} else if (allInnerLines.length > 0) {
// Remove trailing comma from last column if no PK
allInnerLines[allInnerLines.length - 1] = allInnerLines[allInnerLines.length - 1].replace(/,$/, '')
}
// Non-PK index lines (UNIQUE, regular INDEX) — outside CREATE TABLE
const extraIndexLines: string[] = []
for (const idx of indexes) {
if (idx.columns.length === 0 || idx.indexType === 'PrimaryKey') continue
const clustered = idx.isClustered ? 'CLUSTERED' : 'NONCLUSTERED'
const colsSql = idx.columns.map((c) => `[${c.columnName}] ${c.order}`).join(', ')
extraIndexLines.push('')
if (idx.indexType === 'UniqueKey') {
extraIndexLines.push(`-- 🔒 Unique Key: [${idx.indexName}]`)
extraIndexLines.push(`ALTER TABLE ${fullTableName}`)
extraIndexLines.push(` ADD CONSTRAINT [${idx.indexName}] UNIQUE ${clustered} (${colsSql});`)
} else {
extraIndexLines.push(`-- 📋 Index: [${idx.indexName}]`)
extraIndexLines.push(
`CREATE ${idx.isClustered ? 'CLUSTERED ' : ''}INDEX [${idx.indexName}] ON ${fullTableName} (${colsSql});`,
)
}
}
// FK constraint lines
const fkLines: string[] = []
@ -291,42 +338,18 @@ function generateCreateTableSql(
fkLines.push(` ON UPDATE ${cascadeUpdate};`)
}
// Index / Key SQL lines
const indexLines: string[] = []
for (const idx of indexes) {
if (idx.columns.length === 0) continue
const clustered = idx.isClustered ? 'CLUSTERED' : 'NONCLUSTERED'
const colsSql = idx.columns.map((c) => `[${c.columnName}] ${c.order}`).join(', ')
indexLines.push('')
if (idx.indexType === 'PrimaryKey') {
indexLines.push(`-- 🔑 Primary Key: [${idx.indexName}]`)
indexLines.push(`ALTER TABLE ${fullTableName}`)
indexLines.push(` ADD CONSTRAINT [${idx.indexName}] PRIMARY KEY ${clustered} (${colsSql});`)
} else if (idx.indexType === 'UniqueKey') {
indexLines.push(`-- 🔒 Unique Key: [${idx.indexName}]`)
indexLines.push(`ALTER TABLE ${fullTableName}`)
indexLines.push(` ADD CONSTRAINT [${idx.indexName}] UNIQUE ${clustered} (${colsSql});`)
} else {
indexLines.push(`-- 📋 Index: [${idx.indexName}]`)
indexLines.push(
`CREATE ${idx.isClustered ? 'CLUSTERED ' : ''}INDEX [${idx.indexName}] ON ${fullTableName} (${colsSql});`,
)
}
}
const lines: string[] = [
`/* ── Table: ${fullTableName} ── */`,
...(settings.entityName ? [`/* Entity Name: ${settings.entityName} */`] : []),
'',
`CREATE TABLE ${fullTableName}`,
`(`,
...bodyLines,
`);`,
...indexLines,
...(fkLines.length > 0 ? ['/* Foreign Key Constraints */'] : []),
`IF OBJECT_ID(N'${escapedFullTableName}', 'U') IS NULL`,
`BEGIN`,
` CREATE TABLE ${fullTableName}`,
` (`,
...allInnerLines,
` ) ON [PRIMARY]`,
`END`,
`GO`,
...extraIndexLines,
...(fkLines.length > 0 ? ['', '/* Foreign Key Constraints */'] : []),
...fkLines,
'',
`/* Verify: SELECT TOP 10 * FROM ${fullTableName}; */`,
]
return lines.join('\n')