diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs index 56b4879e..bded9251 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/ListFormSeeder_Saas.cs @@ -2702,7 +2702,7 @@ public class ListFormSeeder_Saas : IDataSeedContributor, ITransientDependency }), InsertFieldsDefaultValueJson = DefaultInsertFieldsDefaultValueJson, FormFieldsDefaultValueJson = JsonSerializer.Serialize(new FieldsDefaultValue[] { - new FieldsDefaultValue() { FieldName = "IsDisabled", FieldDbType = DbType.Boolean, Value = "false", CustomValueType = FieldCustomValueTypeEnum.Value } + new() { FieldName = "IsDisabled", FieldDbType = DbType.Boolean, Value = "false", CustomValueType = FieldCustomValueTypeEnum.Value } }) } ); diff --git a/ui/src/views/list/Grid.tsx b/ui/src/views/list/Grid.tsx index 2c48d60f..33659f28 100644 --- a/ui/src/views/list/Grid.tsx +++ b/ui/src/views/list/Grid.tsx @@ -979,16 +979,14 @@ const Grid = (props: GridProps) => { sortedFormDto.forEach((e: any) => { if (e.itemType !== 'tabbed') { - // colCount: max(endpoint.colCount, max(item.colSpan)) - const maxItemColSpan = Math.max( - ...(e.items?.map((i: any) => i.colSpan || 1) || [1]), - ) - const effectiveColCount = Math.max(maxItemColSpan, e.colCount || 1) + // Backend'den gelen colCount ve colSpan değerlerini kullan + const effectiveColCount = e.colCount || 1 + const effectiveColSpan = e.colSpan || 1 result.push({ itemType: e.itemType, colCount: effectiveColCount, - colSpan: e.colSpan, + colSpan: effectiveColSpan, caption: e.caption, // Group'larda caption olmalı items: e.items ?.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1)) @@ -1013,14 +1011,8 @@ const Grid = (props: GridProps) => { colSpan: 1, // caption kullanma! Tabs içindeki title'lar yeterli tabs: tabbedItems.map((tabbedItem: any) => { - // Tab için colCount: max(endpoint.colCount, max(item.colSpan)) - const maxItemColSpan = Math.max( - ...(tabbedItem.items?.map((i: any) => i.colSpan || 1) || [1]), - ) - const effectiveColCount = Math.max( - maxItemColSpan, - tabbedItem.colCount || 1, - ) + // Backend'den gelen colCount ve colSpan değerlerini kullan + const effectiveColCount = tabbedItem.colCount || 1 return { title: tabbedItem.caption, // Her tab'ın title'ı @@ -1094,7 +1086,6 @@ const Grid = (props: GridProps) => { > { const [isPopupFullScreen, setIsPopupFullScreen] = useState(false) const [expandedRowKeys, setExpandedRowKeys] = useState([]) + const preloadExportLibs = () => { + import('exceljs') + import('file-saver') + import('devextreme/excel_exporter') + import('jspdf') + import('devextreme/pdf_exporter') + } + + type EditorOptionsWithButtons = { + buttons?: any[] + } & Record + const defaultSearchParams = useRef(null) useEffect(() => { @@ -112,6 +125,7 @@ const Tree = (props: TreeProps) => { expandAll, collapseAll, getFilter, + isTree: true }) const { filterToolbarData, ...filterData } = useFilters({ @@ -630,6 +644,9 @@ const Tree = (props: TreeProps) => { allowUpdating={gridDto.gridOptions.editingOptionDto?.allowUpdating} allowAdding={gridDto.gridOptions.editingOptionDto?.allowAdding} useIcons={gridDto.gridOptions.editingOptionDto?.useIcons} + confirmDelete={gridDto.gridOptions.editingOptionDto?.confirmDelete} + selectTextOnEditStart={gridDto.gridOptions.editingOptionDto?.selectTextOnEditStart} + startEditAction={gridDto.gridOptions.editingOptionDto?.startEditAction} popup={{ title: (mode === 'new' ? '✚ ' : '🖊️ ') + @@ -657,7 +674,205 @@ const Tree = (props: TreeProps) => { }, ], }} - /> + form={{ + colCount: 1, + onFieldDataChanged: (e) => { + if (e.dataField) { + const formItem = gridDto.gridOptions.editingFormDto + .flatMap((group) => group.items || []) + .find((i) => i.dataField === e.dataField) + if (formItem?.editorScript) { + try { + eval(formItem.editorScript) + } catch (err) { + console.error('Script exec error', err) + } + } + } + }, + items: + gridDto.gridOptions.editingFormDto?.length > 0 + ? (() => { + const sortedFormDto = gridDto.gridOptions.editingFormDto + .slice() + .sort((a: any, b: any) => (a.order >= b.order ? 1 : -1)) + + // Tabbed item'ları grupla + const tabbedItems = sortedFormDto.filter( + (e: any) => e.itemType === 'tabbed', + ) + const result: any[] = [] + + // Helper function: item mapper + const mapFormItem = (i: EditingFormItemDto) => { + let editorOptions: EditorOptionsWithButtons = {} + try { + editorOptions = i.editorOptions && JSON.parse(i.editorOptions) + + if (editorOptions?.buttons) { + editorOptions.buttons = (editorOptions?.buttons || []).map( + (btn: any) => { + if ( + btn?.options?.onClick && + typeof btn.options.onClick === 'string' + ) { + btn.options.onClick = eval(`(${btn.options.onClick})`) + } + return btn + }, + ) + } + + const rawFilter = searchParams?.get('filter') + if (rawFilter) { + const parsed = JSON.parse(rawFilter) + const filters = extractSearchParamsFields(parsed) + + const hasFilter = filters.some( + ([field, op, val]) => field === i.dataField, + ) + + if (hasFilter) { + const existsInExtra = extraFilters.some( + (f) => f.fieldName === i.dataField && !!f.value, + ) + + if (!existsInExtra) { + editorOptions = { + ...editorOptions, + readOnly: true, + } + } + } + } + } catch {} + + const fieldName = i.dataField.split(':')[0] + const listFormField = gridDto.columnFormats.find( + (x: any) => x.fieldName === fieldName, + ) + + if (listFormField?.sourceDbType === DbTypeEnum.Date) { + editorOptions = { + ...{ + type: 'date', + dateSerializationFormat: 'yyyy-MM-dd', + displayFormat: 'shortDate', + }, + ...editorOptions, + } + } else if ( + listFormField?.sourceDbType === DbTypeEnum.DateTime || + listFormField?.sourceDbType === DbTypeEnum.DateTime2 || + listFormField?.sourceDbType === DbTypeEnum.DateTimeOffset + ) { + editorOptions = { + ...{ + type: 'datetime', + dateSerializationFormat: 'yyyy-MM-ddTHH:mm:ssxxx', + displayFormat: 'shortDateShortTime', + }, + ...editorOptions, + } + } + + const item: SimpleItemWithColData = { + canRead: listFormField?.canRead ?? false, + canUpdate: listFormField?.canUpdate ?? false, + canCreate: listFormField?.canCreate ?? false, + canExport: listFormField?.canExport ?? false, + dataField: i.dataField, + name: i.dataField, + editorType2: i.editorType2, + editorType: + i.editorType2 == PlatformEditorTypes.dxGridBox + ? 'dxDropDownBox' + : i.editorType2, + colSpan: i.colSpan, + isRequired: i.isRequired, + editorOptions, + editorScript: i.editorScript, + } + + if (i.dataField.indexOf(':') >= 0) { + item.label = { text: captionize(i.dataField.split(':')[1]) } + } + + if ( + (mode == 'edit' && !item.canUpdate) || + (mode == 'new' && !item.canCreate) + ) { + item.editorOptions = { + ...item.editorOptions, + readOnly: true, + } + } + + return item + } + + sortedFormDto.forEach((e: any) => { + if (e.itemType !== 'tabbed') { + + result.push({ + itemType: e.itemType, + colCount: e.colCount, + colSpan: e.colSpan, + caption: e.caption, // Group'larda caption olmalı + items: e.items + ?.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1)) + .map(mapFormItem) + .filter((a: any) => { + if (mode === 'view') { + return a.canRead + } else if (mode === 'new') { + return a.canCreate || a.canRead + } else if (mode === 'edit') { + return a.canUpdate || a.canRead + } else { + return false + } + }), + }) + } else if (tabbedItems.length > 0 && e === tabbedItems[0]) { + // Tabbed için caption OLMAMALI - sadece tabs array içinde title kullan + result.push({ + itemType: 'tabbed', + colCount: 1, + colSpan: 1, + // caption kullanma! Tabs içindeki title'lar yeterli + tabs: tabbedItems.map((tabbedItem: any) => { + // Backend'den gelen colCount ve colSpan değerlerini kullan + const effectiveColCount = tabbedItem.colCount || 1 + + return { + title: tabbedItem.caption, // Her tab'ın title'ı + colCount: effectiveColCount, + items: tabbedItem.items + ?.sort((a: any, b: any) => (a.order >= b.order ? 1 : -1)) + .map(mapFormItem) + .filter((a: any) => { + if (mode === 'view') { + return a.canRead + } else if (mode === 'new') { + return a.canCreate || a.canRead + } else if (mode === 'edit') { + return a.canUpdate || a.canRead + } else { + return false + } + }), + } + }), + }) + } + }) + + return result + })() + : undefined, + }} + >