From ff3344b3ae59b156739fff008e59cffddc47077e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Wed, 4 Feb 2026 00:30:51 +0300 Subject: [PATCH] =?UTF-8?q?Grid=20Performans=20=C3=A7al=C4=B1=C5=9Fmalar?= =?UTF-8?q?=C4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GridOptionsDto/StateStoringDto.cs | 2 +- ui/src/views/list/Grid.tsx | 45 +++++------ ui/src/views/list/Tree.tsx | 42 ++++++---- .../views/list/useListFormCustomDataSource.ts | 78 +++++++++---------- 4 files changed, 89 insertions(+), 78 deletions(-) diff --git a/api/src/Erp.Platform.Application.Contracts/ListForms/GridOptionsDto/StateStoringDto.cs b/api/src/Erp.Platform.Application.Contracts/ListForms/GridOptionsDto/StateStoringDto.cs index afdf5e72..99d61a61 100644 --- a/api/src/Erp.Platform.Application.Contracts/ListForms/GridOptionsDto/StateStoringDto.cs +++ b/api/src/Erp.Platform.Application.Contracts/ListForms/GridOptionsDto/StateStoringDto.cs @@ -15,6 +15,6 @@ public class StateStoringDto /// Bir kullanıcının bir değişiklik yapması ile bu değişikliğin kaydedilmesi arasındaki gecikmeyi milisaniye cinsinden belirtir. /// [Range(1500, 5000)] - public int SavingTimeout { get; set; } = 2000; + public int SavingTimeout { get; set; } = 5000; } diff --git a/ui/src/views/list/Grid.tsx b/ui/src/views/list/Grid.tsx index 5d0b88aa..346e90a5 100644 --- a/ui/src/views/list/Grid.tsx +++ b/ui/src/views/list/Grid.tsx @@ -553,6 +553,11 @@ const Grid = (props: GridProps) => { [gridDto, cascadeFieldsMap], ) + // StateStoring için storageKey'i memoize et + const storageKey = useMemo(() => { + return gridDto?.gridOptions.stateStoringDto?.storageKey ?? '' + }, [gridDto?.gridOptions.stateStoringDto?.storageKey]) + const customSaveState = useCallback( (state: any) => { if (isEditingRef.current) { @@ -561,27 +566,29 @@ const Grid = (props: GridProps) => { return postListFormCustomization({ listFormCode: listFormCode, customizationType: ListFormCustomizationTypeEnum.GridState, - filterName: `list-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`, + filterName: `list-${storageKey}`, customizationData: JSON.stringify(state), }).then(() => { setGridPanelColor(statedGridPanelColor) }) }, - [listFormCode], + [listFormCode, storageKey], ) const customLoadState = useCallback(() => { return getListFormCustomization( listFormCode, ListFormCustomizationTypeEnum.GridState, - `list-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`, + `list-${storageKey}`, ).then((response: any) => { - setGridPanelColor(statedGridPanelColor) if (response.data?.length > 0) { + setGridPanelColor(statedGridPanelColor) return JSON.parse(response.data[0].customizationData) } + // Veri yoksa null dön (DevExtreme bunu default state olarak algılar) + return null }) - }, [listFormCode]) + }, [listFormCode, storageKey]) useEffect(() => { if (gridRef?.current) { @@ -778,12 +785,11 @@ const Grid = (props: GridProps) => { const instance = gridRef?.current?.instance() if (instance) { instance.option('remoteOperations', { - groupPaging: true, + paging: true, filtering: true, sorting: true, - paging: true, - grouping: true, - summary: true, + grouping: false, + summary: false, }) instance.option('dataSource', gridDataSource) } @@ -824,9 +830,13 @@ const Grid = (props: GridProps) => { stateStoring.customLoad = () => customLoadStateRef.current() } instance.option('stateStoring', stateStoring) - instance.state(null) + + // State'i yükle - dataSource ve columns hazır olduğunda + if (gridDataSource && columnData) { + instance.state(undefined) // undefined = reload from storage + } } - }, [gridDto]) // Sadece gridDto'ya bağlı + }, [gridDto, gridDataSource, columnData]) // dataSource ve columns hazır olduğunda state yükle useEffect(() => { refListFormCode.current = listFormCode @@ -1069,18 +1079,8 @@ const Grid = (props: GridProps) => {
0 ? gridDto.gridOptions.height @@ -1162,6 +1162,7 @@ const Grid = (props: GridProps) => { } startEditAction={gridDto.gridOptions.editingOptionDto?.startEditAction} popup={{ + deferRendering: true, animation: {}, title: (mode === 'new' ? '✚ ' : '🖊️ ') + diff --git a/ui/src/views/list/Tree.tsx b/ui/src/views/list/Tree.tsx index c740c4bf..5ec793bb 100644 --- a/ui/src/views/list/Tree.tsx +++ b/ui/src/views/list/Tree.tsx @@ -551,6 +551,11 @@ const Tree = (props: TreeProps) => { } } + // StateStoring için storageKey'i memoize et + const storageKey = useMemo(() => { + return gridDto?.gridOptions.stateStoringDto?.storageKey ?? '' + }, [gridDto?.gridOptions.stateStoringDto?.storageKey]) + const customSaveState = useCallback( (state: any) => { if (isEditingRef.current) { @@ -559,29 +564,29 @@ const Tree = (props: TreeProps) => { return postListFormCustomization({ listFormCode: listFormCode, customizationType: ListFormCustomizationTypeEnum.GridState, - filterName: `tree-${gridRef.current?.instance().option('stateStoring')?.storageKey ?? ''}`, + filterName: `tree-${storageKey}`, customizationData: JSON.stringify(state), }).then(() => { setGridPanelColor(statedGridPanelColor) }) }, - [listFormCode], + [listFormCode, storageKey], ) - const customLoadState = useCallback( - () => - getListFormCustomization( - listFormCode, - ListFormCustomizationTypeEnum.GridState, - `tree-${gridRef.current?.instance().option('stateStoring')?.storageKey ?? ''}`, - ).then((response: any) => { + const customLoadState = useCallback(() => { + return getListFormCustomization( + listFormCode, + ListFormCustomizationTypeEnum.GridState, + `tree-${storageKey}`, + ).then((response: any) => { + if (response.data?.length > 0) { setGridPanelColor(statedGridPanelColor) - if (response.data?.length > 0) { - return JSON.parse(response.data[0].customizationData) - } - }), - [listFormCode], - ) + return JSON.parse(response.data[0].customizationData) + } + // Veri yoksa null dön (DevExtreme bunu default state olarak algılar) + return null + }) + }, [listFormCode, storageKey]) // StateStoring fonksiyonlarını ref'e kaydet - Grid'deki gibi const customSaveStateRef = useRef(customSaveState) @@ -754,7 +759,12 @@ const Tree = (props: TreeProps) => { stateStoring.customLoad = () => customLoadStateRef.current() } gridRef?.current?.instance().option('stateStoring', stateStoring) - }, [columnData]) + + // State'i yükle - dataSource ve columns hazır olduğunda + if (treeListDataSource && columnData) { + gridRef?.current?.instance().state(undefined) // undefined = reload from storage + } + }, [columnData, treeListDataSource, gridDto]) // dataSource ve columns hazır olduğunda state yükle return ( <> diff --git a/ui/src/views/list/useListFormCustomDataSource.ts b/ui/src/views/list/useListFormCustomDataSource.ts index 19a66d95..855aaf8c 100644 --- a/ui/src/views/list/useListFormCustomDataSource.ts +++ b/ui/src/views/list/useListFormCustomDataSource.ts @@ -275,50 +275,50 @@ const useListFormCustomDataSource = ({ return null } }, - totalCount: async (loadOptions) => { - const parameters = getLoadOptions(loadOptions, { - listFormCode, - filter: '', - createDeleteQuery: searchParams?.get('createDeleteQuery'), - group: '', - }) + // totalCount: async (loadOptions) => { + // const parameters = getLoadOptions(loadOptions, { + // listFormCode, + // filter: '', + // createDeleteQuery: searchParams?.get('createDeleteQuery'), + // group: '', + // }) - // 1. Default filter'ı al - const defaultFilter = searchParams?.get('filter') - ? JSON.parse(searchParams.get('filter')!) - : null + // // 1. Default filter'ı al + // const defaultFilter = searchParams?.get('filter') + // ? JSON.parse(searchParams.get('filter')!) + // : null - let combinedFilter: any = parameters.filter + // let combinedFilter: any = parameters.filter - // 2. Eğer hem default hem de grid filter varsa merge et - if (defaultFilter && combinedFilter) { - combinedFilter = [defaultFilter, 'and', combinedFilter] - } else if (defaultFilter) { - combinedFilter = defaultFilter - } + // // 2. Eğer hem default hem de grid filter varsa merge et + // if (defaultFilter && combinedFilter) { + // combinedFilter = [defaultFilter, 'and', combinedFilter] + // } else if (defaultFilter) { + // combinedFilter = defaultFilter + // } - if (combinedFilter && combinedFilter.length > 0) { - parameters.filter = JSON.stringify(combinedFilter) - } else { - delete parameters.filter // hiç göndermesin - } + // if (combinedFilter && combinedFilter.length > 0) { + // parameters.filter = JSON.stringify(combinedFilter) + // } else { + // delete parameters.filter // hiç göndermesin + // } - try { - const response = await dynamicFetch('list-form-select/select', 'GET', parameters) - return response.data.totalCount - } catch (error: any) { - // toast.push( - // - // TotalCount error - // {error.toString()} - // , - // { - // placement: 'top-end', - // }, - // ) - return null - } - }, + // try { + // const response = await dynamicFetch('list-form-select/select', 'GET', parameters) + // return response.data.totalCount + // } catch (error: any) { + // // toast.push( + // // + // // TotalCount error + // // {error.toString()} + // // , + // // { + // // placement: 'top-end', + // // }, + // // ) + // return null + // } + // }, byKey: async (key) => { const parameters = getLoadOptions( { key },