From 401db7bfef4037a2045a1cce75dc5a0e52790f0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Sat, 21 Mar 2026 21:51:27 +0300 Subject: [PATCH] =?UTF-8?q?Wizard=20taraf=C4=B1nda=20kolayla=C5=9Ft=C4=B1r?= =?UTF-8?q?=C4=B1c=C4=B1=20=C3=B6zellikler?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Seeds/LanguagesData.json | 6 +++ .../Seeds/ListFormSeeder_Saas.cs | 18 +++++--- ui/src/views/admin/listForm/Wizard.tsx | 44 +++++++++++++++++-- ui/src/views/admin/listForm/WizardStep1.tsx | 15 +++++-- ui/src/views/shared/MenuAddDialog.tsx | 21 +++++++-- 5 files changed, 87 insertions(+), 17 deletions(-) diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json index e9c5f7b..e19164c 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/LanguagesData.json @@ -16052,6 +16052,12 @@ "en": "Optional", "tr": "İsteğe Bağlı" }, + { + "resourceName": "Platform", + "key": "ListForms.Wizard.Step1.Order", + "en": "Order", + "tr": "Sıra" + }, { "resourceName": "Platform", "key": "ListForms.Wizard.Step1.WizardName", diff --git a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs index c03975f..fea3d75 100644 --- a/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs +++ b/api/src/Sozsoft.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs @@ -1060,7 +1060,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency new() { Order=1, ColCount=1, ColSpan=1, ItemType="group", Items = [ new EditingFormItemDto { Order=1, DataField="System", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=2, DataField="Group", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, - new EditingFormItemDto { Order=3, DataField="Term", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, + new EditingFormItemDto { Order=3, DataField="Term", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxSelectBox, EditorOptions=EditorOptionValues.ShowClearButton }, new EditingFormItemDto { Order=4, DataField="Url", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxTextBox }, new EditingFormItemDto { Order=5, DataField="Weight", ColSpan=1, IsRequired=true, EditorType2=EditorTypes.dxNumberBox, EditorOptions=EditorOptionValues.NumberStandartFormat() }, ]} @@ -1080,7 +1080,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency CultureName = LanguageCodes.En, SourceDbType = DbType.Int32, FieldName = "Id", - CaptionName = "App.Listform.ListformField.Id", + CaptionName = "App.Listform.ListformField.Id", Width = 100, ListOrderNo = 1, Visible = false, @@ -1095,7 +1095,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency CultureName = LanguageCodes.En, SourceDbType = DbType.String, FieldName = "System", - CaptionName = "App.Listform.ListformField.System", + CaptionName = "App.Listform.ListformField.System", Width = 100, ListOrderNo = 2, Visible = true, @@ -1111,7 +1111,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency CultureName = LanguageCodes.En, SourceDbType = DbType.String, FieldName = "Group", - CaptionName = "App.Listform.ListformField.Group", + CaptionName = "App.Listform.ListformField.Group", Width = 400, ListOrderNo = 3, Visible = true, @@ -1127,15 +1127,21 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency CultureName = LanguageCodes.En, SourceDbType = DbType.String, FieldName = "Term", - CaptionName = "App.Listform.ListformField.Term", + CaptionName = "App.Listform.ListformField.Term", Width = 400, ListOrderNo = 4, Visible = true, IsActive = true, IsDeleted = false, AllowSearch = true, + LookupJson = JsonSerializer.Serialize(new LookupDto { + DataSourceType = UiLookupDataSourceTypeEnum.Query, + DisplayExpr = "Name", + ValueExpr = "Key", + LookupQuery = LookupQueryValues.LanguageKeyValues + }), ColumnCustomizationJson = DefaultColumnCustomizationJson, - PermissionJson = DefaultFieldPermissionJson(listForm.Name), + PermissionJson = DefaultFieldPermissionJson(listForm.Name), PivotSettingsJson = DefaultPivotSettingsJson }, new() { diff --git a/ui/src/views/admin/listForm/Wizard.tsx b/ui/src/views/admin/listForm/Wizard.tsx index 5dce2b7..375e2be 100644 --- a/ui/src/views/admin/listForm/Wizard.tsx +++ b/ui/src/views/admin/listForm/Wizard.tsx @@ -137,6 +137,20 @@ const Wizard = () => { // ── Editing Form Groups (Step 3) ── const [editingGroups, setEditingGroups] = useState([]) + // Audit columns that should not be selected by default + const AUDIT_COLUMNS = new Set([ + 'creationtime', + 'creatorid', + 'lastmodificationtime', + 'lastmodifierid', + 'isdeleted', + 'deletiontime', + 'deleterid', + ]) + + const isAuditColumn = (columnName: string) => + AUDIT_COLUMNS.has(columnName.toLowerCase()) + const loadColumns = async (dsCode: string, schema: string, name: string) => { if (!dsCode || !name) { setSelectCommandColumns([]) @@ -149,7 +163,8 @@ const Wizard = () => { const res = await sqlObjectManagerService.getTableColumns(dsCode, schema, name) const cols = res.data ?? [] setSelectCommandColumns(cols) - setSelectedColumns(new Set(cols.map((c) => c.columnName))) + const selectableColumns = cols.filter((c) => !isAuditColumn(c.columnName)) + setSelectedColumns(new Set(selectableColumns.map((c) => c.columnName))) setEditingGroups([]) // Auto-select first column as key field if (cols.length > 0) { @@ -176,7 +191,15 @@ const Wizard = () => { }) const toggleAllColumns = (all: boolean) => - setSelectedColumns(all ? new Set(selectCommandColumns.map((c) => c.columnName)) : new Set()) + setSelectedColumns( + all + ? new Set( + selectCommandColumns + .filter((c) => !isAuditColumn(c.columnName)) + .map((c) => c.columnName), + ) + : new Set(), + ) const getDataSourceList = async () => { setIsLoadingDataSource(true) @@ -235,11 +258,26 @@ const Wizard = () => { return sanitized ? `App.Wizard.${sanitized}` : '' } + const toSpacedLabel = (value: string) => + value + .replace(/([a-z0-9])([A-Z])/g, '$1 $2') + .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2') + .trim() + + const handleWizardNameChange = (name: string) => { - formikRef.current?.setFieldValue('wizardName', name) + const spacedLabel = toSpacedLabel(name) const derived = deriveListFormCode(name) + + formikRef.current?.setFieldValue('wizardName', name) formikRef.current?.setFieldValue('listFormCode', derived) formikRef.current?.setFieldValue('menuCode', derived) + formikRef.current?.setFieldValue('languageTextMenuEn', spacedLabel) + formikRef.current?.setFieldValue('languageTextMenuTr', spacedLabel) + formikRef.current?.setFieldValue('languageTextTitleEn', spacedLabel) + formikRef.current?.setFieldValue('languageTextTitleTr', spacedLabel) + formikRef.current?.setFieldValue('languageTextDescEn', spacedLabel) + formikRef.current?.setFieldValue('languageTextDescTr', spacedLabel) } const handleMenuParentChange = (code: string) => { diff --git a/ui/src/views/admin/listForm/WizardStep1.tsx b/ui/src/views/admin/listForm/WizardStep1.tsx index e0bfca7..907400d 100644 --- a/ui/src/views/admin/listForm/WizardStep1.tsx +++ b/ui/src/views/admin/listForm/WizardStep1.tsx @@ -6,7 +6,7 @@ import navigationIcon from '@/proxy/menus/navigation-icon.config' import { MenuItem } from '@/proxy/menus/menu' import { MenuService } from '@/services/menu.service' import { Field, FieldProps, FormikErrors, FormikTouched } from 'formik' -import { useEffect, useState } from 'react' +import { useEffect, useMemo, useState } from 'react' import CreatableSelect from 'react-select/creatable' import { FaArrowRight, @@ -411,7 +411,15 @@ const WizardStep1 = ({ }: WizardStep1Props) => { const [menuDialogOpen, setMenuDialogOpen] = useState(false) const [menuDialogParentCode, setMenuDialogParentCode] = useState('') - const [menuDialogInitialOrder, setMenuDialogInitialOrder] = useState(999) + + const menuDialogInitialOrder = useMemo(() => { + const maxOrder = rawMenuItems.reduce((max, item) => { + const order = typeof item.order === 'number' ? item.order : 0 + return order > max ? order : max + }, 0) + + return maxOrder + 100 + }, [rawMenuItems]) const step1Missing = [ !wizardName && translate('::ListForms.Wizard.Step1.WizardName'), @@ -419,6 +427,7 @@ const WizardStep1 = ({ !values.permissionGroupName && translate('::ListForms.Wizard.Step1.PermissionGroupName'), !values.languageTextMenuEn && translate('::ListForms.Wizard.Step4.MenuEn'), !values.languageTextMenuTr && translate('::ListForms.Wizard.Step4.MenuTr'), + !values.menuIcon && translate('::ListForms.Wizard.Step4.MenuIcon'), ].filter(Boolean) as string[] const step1CanGo = step1Missing.length === 0 @@ -464,8 +473,6 @@ const WizardStep1 = ({ ? findRootCode(rawMenuItems, values.menuParentCode) : '', ) - const selectedItem = rawMenuItems.find((i) => i.code === values.menuParentCode) - setMenuDialogInitialOrder(selectedItem?.order ?? 999) setMenuDialogOpen(true) }} className="flex items-center gap-1 px-2 py-0.5 text-xs rounded bg-green-500 text-white hover:bg-green-600" diff --git a/ui/src/views/shared/MenuAddDialog.tsx b/ui/src/views/shared/MenuAddDialog.tsx index 7d1f876..f4a3fae 100644 --- a/ui/src/views/shared/MenuAddDialog.tsx +++ b/ui/src/views/shared/MenuAddDialog.tsx @@ -203,6 +203,13 @@ export function MenuAddDialog({ 'h-11 px-3 py-2 rounded-lg border border-gray-200 dark:border-gray-700 bg-gray-50 dark:bg-gray-700 text-sm text-gray-400 dark:text-gray-500 cursor-not-allowed w-full' const labelCls = 'text-xs font-medium text-gray-500 dark:text-gray-400 mb-1' + const toCodeToken = (value: string) => value.replace(/\s+/g, '') + const toSpacedLabel = (value: string) => + value + .replace(/([a-z0-9])([A-Z])/g, '$1 $2') + .replace(/([A-Z])([A-Z][a-z])/g, '$1 $2') + .trim() + return (
@@ -224,13 +231,19 @@ export function MenuAddDialog({ + onChange={(e) => { + const codeToken = toCodeToken(e.target.value) + const spacedLabel = toSpacedLabel(codeToken) + setForm((p) => ({ ...p, - name: e.target.value.replace(/\s+/g, ''), - code: `App.Wizard.${e.target.value.replace(/\s+/g, '')}`, + name: codeToken, + code: `App.Wizard.${codeToken}`, + menuTextEn: spacedLabel, + menuTextTr: spacedLabel, + shortName: codeToken.substring(0, 3), })) - } + }} placeholder="MyMenu" className={fieldCls} />