Wizard Güncellemeleri
This commit is contained in:
parent
63695be34e
commit
ac7784c030
7 changed files with 143 additions and 8 deletions
|
|
@ -11,4 +11,6 @@ public class WizardColumnItemInputDto
|
|||
public int ColSpan { get; set; } = 1;
|
||||
public bool IsRequired { get; set; }
|
||||
public DbType DbSourceType { get; set; } = DbType.String;
|
||||
public string TurkishCaption { get; set; }
|
||||
public string EnglishCaption { get; set; }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -229,22 +229,31 @@ public class ListFormWizardAppService(
|
|||
|
||||
// ListFormField - each item in each group becomes a visible field record
|
||||
var fieldOrder = 0;
|
||||
var captionName = string.Empty;
|
||||
foreach (var group in input.Groups)
|
||||
{
|
||||
foreach (var item in group.Items)
|
||||
{
|
||||
fieldOrder++;
|
||||
captionName = $"App.Listform.ListformField.{item.DataField}";
|
||||
await repoListFormField.InsertAsync(new ListFormField
|
||||
{
|
||||
ListFormCode = input.ListFormCode,
|
||||
FieldName = item.DataField,
|
||||
CaptionName = item.DataField,
|
||||
CaptionName = captionName,
|
||||
Visible = item.DataField != input.KeyFieldName,
|
||||
IsActive = true,
|
||||
AllowSearch = true,
|
||||
ListOrderNo = fieldOrder,
|
||||
SourceDbType = item.DbSourceType,
|
||||
CultureName = PlatformConsts.DefaultLanguage,
|
||||
PermissionJson = WizardConsts.DefaultFieldPermissionJson(code),
|
||||
ColumnCustomizationJson = WizardConsts.DefaultColumnCustomizationJson,
|
||||
ColumnFilterJson = WizardConsts.DefaultColumnFilteringJson,
|
||||
PivotSettingsJson = WizardConsts.DefaultPivotSettingsJson,
|
||||
}, autoSave: false);
|
||||
|
||||
await CreateLangKey(captionName, item.EnglishCaption, item.TurkishCaption);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16304,6 +16304,18 @@
|
|||
"en": "Columns load after selecting a Select Command",
|
||||
"tr": "Select Command seçince sütunlar yüklenir"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.Wizard.Step3.TurkishCaption",
|
||||
"en": "Turkish Caption",
|
||||
"tr": "Türkçe Başlık"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.Wizard.Step3.EnglishCaption",
|
||||
"en": "English Caption",
|
||||
"tr": "İngilizce Başlık"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.Wizard.Step3.EditorOptions",
|
||||
|
|
|
|||
|
|
@ -2,6 +2,11 @@ using System.Data;
|
|||
using System.Text.Json;
|
||||
using Sozsoft.Platform.Enums;
|
||||
using static Sozsoft.Platform.PlatformConsts;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Globalization;
|
||||
|
||||
public static class WizardConsts
|
||||
{
|
||||
|
|
@ -26,6 +31,44 @@ public static class WizardConsts
|
|||
public static string MenuUrl(string code) => $"/admin/list/{code}";
|
||||
public static string MenuIcon => "FcList";
|
||||
|
||||
public static class LabelHelper
|
||||
{
|
||||
public static string GetCamelCaseLabel<T>(string propertyName)
|
||||
{
|
||||
var prop = typeof(T).GetProperty(propertyName);
|
||||
if (prop == null)
|
||||
return propertyName;
|
||||
|
||||
// 1. Display varsa direkt onu kullan
|
||||
var displayAttr = prop.GetCustomAttribute<DisplayAttribute>();
|
||||
if (displayAttr != null && !string.IsNullOrWhiteSpace(displayAttr.Name))
|
||||
return displayAttr.Name;
|
||||
|
||||
// 2. CamelCase → kelimelere ayır
|
||||
var words = Regex
|
||||
.Split(propertyName, "(?=[A-Z])")
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||
.ToList();
|
||||
|
||||
// 3. Türkçe karakter dönüşümü + düzgün büyük harf
|
||||
var culture = new CultureInfo("tr-TR");
|
||||
|
||||
words = words.Select(w =>
|
||||
{
|
||||
w = w.ToLower(culture);
|
||||
|
||||
// Türkçe karakter normalize (genel yaklaşım)
|
||||
w = w
|
||||
.Replace("i", "i") // bilinçli bırakıyoruz
|
||||
.Replace("ı", "ı"); // zaten doğru
|
||||
|
||||
return culture.TextInfo.ToTitleCase(w);
|
||||
}).ToList();
|
||||
|
||||
return string.Join(" ", words);
|
||||
}
|
||||
}
|
||||
|
||||
public static readonly string DefaultExportJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
Enabled = true,
|
||||
|
|
@ -83,6 +126,33 @@ public static class WizardConsts
|
|||
});
|
||||
}
|
||||
|
||||
public static string DefaultFieldPermissionJson(string permissionName)
|
||||
{
|
||||
return JsonSerializer.Serialize(new
|
||||
{
|
||||
C = permissionName + ".Create",
|
||||
R = permissionName,
|
||||
U = permissionName + ".Update",
|
||||
E = true,
|
||||
I = false,
|
||||
Deny = false
|
||||
});
|
||||
}
|
||||
|
||||
public static readonly string DefaultColumnCustomizationJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
AllowReordering = true,
|
||||
});
|
||||
|
||||
public static readonly string DefaultColumnFilteringJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
AllowFiltering = true,
|
||||
});
|
||||
public static readonly string DefaultPivotSettingsJson = JsonSerializer.Serialize(new
|
||||
{
|
||||
IsPivot = true
|
||||
});
|
||||
|
||||
public static string DefaultDeleteCommand(string tableName)
|
||||
{
|
||||
return $"UPDATE \"{tableName}\" SET \"DeleterId\"=@DeleterId, \"DeletionTime\"=CURRENT_TIMESTAMP, \"IsDeleted\"='true' WHERE \"Id\"=@Id";
|
||||
|
|
|
|||
|
|
@ -324,13 +324,14 @@ const Wizard = () => {
|
|||
const col = selectCommandColumns.find((c) => c.columnName === item.dataField)
|
||||
return {
|
||||
dataField: item.dataField,
|
||||
captionName: `App.Listform.ListformField.${item.dataField}`,
|
||||
editorType: item.editorType,
|
||||
editorOptions: item.editorOptions ?? '',
|
||||
editorScript: item.editorScript ?? '',
|
||||
colSpan: item.colSpan,
|
||||
isRequired: item.isRequired,
|
||||
dbSourceType: col ? sqlDataTypeToDbType(col.dataType) : 12, // 12 = DbType.String
|
||||
turkishCaption: item.turkishCaption,
|
||||
englishCaption: item.englishCaption,
|
||||
}
|
||||
}),
|
||||
})),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ export interface WizardGroupItem {
|
|||
editorScript: string
|
||||
colSpan: number
|
||||
isRequired: boolean
|
||||
turkishCaption?: string
|
||||
englishCaption?: string
|
||||
}
|
||||
|
||||
export interface WizardGroup {
|
||||
|
|
@ -70,6 +72,18 @@ function inferEditorType(sqlType: string): string {
|
|||
return 'dxTextBox'
|
||||
}
|
||||
|
||||
const formatLabel = (text: string) => {
|
||||
return text
|
||||
// CamelCase → kelimelere ayır
|
||||
.split(/(?=[A-Z])/)
|
||||
.filter(Boolean)
|
||||
.map(word =>
|
||||
word.charAt(0).toUpperCase() +
|
||||
word.slice(1).toLowerCase()
|
||||
)
|
||||
.join(" ");
|
||||
};
|
||||
|
||||
function newGroupItem(colName: string, sqlType = ''): WizardGroupItem {
|
||||
return {
|
||||
id: `${colName}_${Date.now()}`,
|
||||
|
|
@ -79,6 +93,8 @@ function newGroupItem(colName: string, sqlType = ''): WizardGroupItem {
|
|||
editorScript: '',
|
||||
colSpan: 1,
|
||||
isRequired: false,
|
||||
turkishCaption: formatLabel(colName),
|
||||
englishCaption: formatLabel(colName),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -123,6 +139,8 @@ function AvailableColumnChip({ colName }: { colName: string }) {
|
|||
interface SortableItemProps {
|
||||
item: WizardGroupItem
|
||||
groupColCount: number
|
||||
onTurkishCaptionChange: (val: string) => void
|
||||
onEnglishCaptionChange: (val: string) => void
|
||||
onEditorTypeChange: (val: string) => void
|
||||
onEditorOptionsChange: (val: string) => void
|
||||
onEditorScriptChange: (val: string) => void
|
||||
|
|
@ -134,6 +152,8 @@ interface SortableItemProps {
|
|||
function SortableItem({
|
||||
item,
|
||||
groupColCount,
|
||||
onTurkishCaptionChange,
|
||||
onEnglishCaptionChange,
|
||||
onEditorTypeChange,
|
||||
onEditorOptionsChange,
|
||||
onEditorScriptChange,
|
||||
|
|
@ -198,14 +218,33 @@ function SortableItem({
|
|||
))}
|
||||
</select>
|
||||
|
||||
{/* Turkish Caption */}
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[10px] text-gray-400 font-medium">{translate('::ListForms.Wizard.Step3.TurkishCaption')}</span>
|
||||
<input
|
||||
value={item.turkishCaption}
|
||||
onChange={(e) => onTurkishCaptionChange(e.target.value)}
|
||||
className="w-full text-xs px-1.5 py-1 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400 resize-none font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* English Caption */}
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[10px] text-gray-400 font-medium">{translate('::ListForms.Wizard.Step3.EnglishCaption')}</span>
|
||||
<input
|
||||
value={item.englishCaption}
|
||||
onChange={(e) => onEnglishCaptionChange(e.target.value)}
|
||||
className="w-full text-xs px-1.5 py-1 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400 resize-none font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Editor Options */}
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<span className="text-[10px] text-gray-400 font-medium">{translate('::ListForms.Wizard.Step3.EditorOptions')}</span>
|
||||
<textarea
|
||||
<input
|
||||
value={item.editorOptions}
|
||||
onChange={(e) => onEditorOptionsChange(e.target.value)}
|
||||
placeholder='{"readOnly": false}'
|
||||
rows={2}
|
||||
className="w-full text-xs px-1.5 py-1 rounded border border-gray-200 dark:border-gray-600 bg-gray-50 dark:bg-gray-700 text-gray-700 dark:text-gray-200 focus:outline-none focus:border-indigo-400 resize-none font-mono"
|
||||
/>
|
||||
</div>
|
||||
|
|
@ -360,6 +399,8 @@ function GroupCard({
|
|||
key={item.id}
|
||||
item={item}
|
||||
groupColCount={group.colCount}
|
||||
onTurkishCaptionChange={(val) => onItemChange(item.id, { turkishCaption: val })}
|
||||
onEnglishCaptionChange={(val) => onItemChange(item.id, { englishCaption: val })}
|
||||
onEditorTypeChange={(val) => onItemChange(item.id, { editorType: val })}
|
||||
onEditorOptionsChange={(val) => onItemChange(item.id, { editorOptions: val })}
|
||||
onEditorScriptChange={(val) => onItemChange(item.id, { editorScript: val })}
|
||||
|
|
@ -405,7 +446,7 @@ const WizardStep3 = ({
|
|||
? [
|
||||
{
|
||||
id: `grp_default_${Date.now()}`,
|
||||
caption: 'Group 1',
|
||||
caption: '',
|
||||
colCount: 2,
|
||||
items: [] as WizardGroupItem[],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -269,7 +269,7 @@ const WizardStep4 = ({
|
|||
badge={`${g.items.length} ${translate('::ListForms.Wizard.Step4.StatField')} · ${g.colCount} ${translate('::ListForms.Wizard.Step4.StatColumn')}`}
|
||||
defaultOpen={false}
|
||||
>
|
||||
<div className="flex flex-col gap-0.5">
|
||||
<div className="grid grid-cols-2 gap-2">
|
||||
{g.items.length === 0 ? (
|
||||
<span className="text-xs text-gray-300 italic">{translate('::ListForms.Wizard.Step4.NoFields') || 'Alan yok'}</span>
|
||||
) : (
|
||||
|
|
@ -284,8 +284,8 @@ const WizardStep4 = ({
|
|||
<span className="text-[10px] text-gray-400 bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded">
|
||||
{item.editorType}
|
||||
</span>
|
||||
<span className="text-[10px] text-gray-400 ml-auto shrink-0">
|
||||
span:{item.colSpan}
|
||||
<span className="text-[10px] text-gray-400 mr-auto shrink-0 bg-gray-100 dark:bg-gray-800 px-1.5 py-0.5 rounded">
|
||||
col-span-{item.colSpan}
|
||||
{item.isRequired && (
|
||||
<span className="ml-1 text-red-400 font-semibold">*</span>
|
||||
)}
|
||||
|
|
|
|||
Loading…
Reference in a new issue