Grid ve Tree state değişiklikleri
This commit is contained in:
parent
5d7db888ec
commit
cd67bd2b06
4 changed files with 188 additions and 149 deletions
|
|
@ -3210,6 +3210,12 @@
|
|||
"en": "Reset Grid State",
|
||||
"tr": "Tablo Yapısını Sıfırla"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListForm.GridStateReset",
|
||||
"en": "Grid State Reset",
|
||||
"tr": "Tablo Yapısı Sıfırlandı"
|
||||
},
|
||||
{
|
||||
"resourceName": "Platform",
|
||||
"key": "ListForms.ListForm.SaveFilter",
|
||||
|
|
|
|||
|
|
@ -131,10 +131,53 @@ const Grid = (props: GridProps) => {
|
|||
}
|
||||
}, [searchParams])
|
||||
|
||||
// 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) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return postListFormCustomization({
|
||||
listFormCode: listFormCode,
|
||||
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||
filterName: `list-${storageKey}`,
|
||||
customizationData: JSON.stringify(state),
|
||||
})
|
||||
.then(() => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
toast.push(
|
||||
<Notification type="success" duration={2000}>
|
||||
{translate('::ListForms.ListForm.GridStateSaved')}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.push(
|
||||
<Notification type="danger" duration={2500}>
|
||||
{translate('::ListForms.ListForm.GridStateSaveError')}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
throw err
|
||||
})
|
||||
},
|
||||
[listFormCode, storageKey, translate],
|
||||
)
|
||||
|
||||
const { filterToolbarData, ...filterData } = useFilters({
|
||||
gridDto,
|
||||
gridRef,
|
||||
listFormCode,
|
||||
saveGridState: customSaveState,
|
||||
})
|
||||
|
||||
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
|
||||
|
|
@ -415,8 +458,12 @@ const Grid = (props: GridProps) => {
|
|||
|
||||
gridDto.columnFormats.forEach((col) => {
|
||||
if (col.lookupDto?.cascadeParentFields && col.fieldName) {
|
||||
const parentFields = col.lookupDto.cascadeParentFields.split(',').map((f: string) => f.trim())
|
||||
const childFields = col.lookupDto.cascadeEmptyFields?.split(',').map((f: string) => f.trim())
|
||||
const parentFields = col.lookupDto.cascadeParentFields
|
||||
.split(',')
|
||||
.map((f: string) => f.trim())
|
||||
const childFields = col.lookupDto.cascadeEmptyFields
|
||||
?.split(',')
|
||||
.map((f: string) => f.trim())
|
||||
|
||||
cascadeMap.set(col.fieldName, {
|
||||
parentFields,
|
||||
|
|
@ -557,28 +604,6 @@ 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) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return postListFormCustomization({
|
||||
listFormCode: listFormCode,
|
||||
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||
filterName: `list-${storageKey}`,
|
||||
customizationData: JSON.stringify(state),
|
||||
}).then(() => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
})
|
||||
},
|
||||
[listFormCode, storageKey],
|
||||
)
|
||||
|
||||
const customLoadState = useCallback(() => {
|
||||
return getListFormCustomization(
|
||||
listFormCode,
|
||||
|
|
@ -810,13 +835,15 @@ const Grid = (props: GridProps) => {
|
|||
|
||||
const instance = gridRef?.current?.instance()
|
||||
if (instance) {
|
||||
customLoadState().then((state) => {
|
||||
if (state) {
|
||||
instance.state(state)
|
||||
}
|
||||
}).catch((err) => {
|
||||
console.error('State load error:', err)
|
||||
})
|
||||
customLoadState()
|
||||
.then((state) => {
|
||||
if (state) {
|
||||
instance.state(state)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('State load error:', err)
|
||||
})
|
||||
}
|
||||
}, [gridDto, gridDataSource, columnData])
|
||||
|
||||
|
|
@ -1021,10 +1048,7 @@ const Grid = (props: GridProps) => {
|
|||
})
|
||||
|
||||
const buffer = await workbook.csv.writeBuffer()
|
||||
saveAs(
|
||||
new Blob([buffer], { type: 'text/csv' }),
|
||||
`${listFormCode}_export.csv`,
|
||||
)
|
||||
saveAs(new Blob([buffer], { type: 'text/csv' }), `${listFormCode}_export.csv`)
|
||||
} else if (e.format === 'pdf') {
|
||||
// jspdf + devextreme pdf exporter => ihtiyaç anında yükle
|
||||
const [jspdfMod, { exportDataGrid: exportDataPdf }] = await Promise.all([
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import TreeListDx, {
|
|||
FilterPanel,
|
||||
FilterRow,
|
||||
HeaderFilter,
|
||||
IStateStoringProps,
|
||||
LoadPanel,
|
||||
Pager,
|
||||
Paging,
|
||||
|
|
@ -126,10 +125,68 @@ const Tree = (props: TreeProps) => {
|
|||
}
|
||||
}, [searchParams])
|
||||
|
||||
// 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) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return postListFormCustomization({
|
||||
listFormCode: listFormCode,
|
||||
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||
filterName: `tree-${storageKey}`,
|
||||
customizationData: JSON.stringify(state),
|
||||
})
|
||||
.then(() => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
toast.push(
|
||||
<Notification type="success" duration={2000}>
|
||||
{translate('::ListForms.ListForm.GridStateSaved')}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.push(
|
||||
<Notification type="danger" duration={2500}>
|
||||
{translate('::ListForms.ListForm.GridStateSaveError')}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
throw err
|
||||
})
|
||||
},
|
||||
[listFormCode, storageKey, translate],
|
||||
)
|
||||
|
||||
const customLoadState = useCallback(() => {
|
||||
return getListFormCustomization(
|
||||
listFormCode,
|
||||
ListFormCustomizationTypeEnum.GridState,
|
||||
`tree-${storageKey}`,
|
||||
).then((response: any) => {
|
||||
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, storageKey])
|
||||
|
||||
const { filterToolbarData, ...filterData } = useFilters({
|
||||
gridDto,
|
||||
gridRef,
|
||||
listFormCode,
|
||||
saveGridState: customSaveState,
|
||||
})
|
||||
|
||||
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
|
||||
|
|
@ -543,52 +600,6 @@ 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) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
return postListFormCustomization({
|
||||
listFormCode: listFormCode,
|
||||
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||
filterName: `tree-${storageKey}`,
|
||||
customizationData: JSON.stringify(state),
|
||||
}).then(() => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
})
|
||||
},
|
||||
[listFormCode, storageKey],
|
||||
)
|
||||
|
||||
const customLoadState = useCallback(() => {
|
||||
return getListFormCustomization(
|
||||
listFormCode,
|
||||
ListFormCustomizationTypeEnum.GridState,
|
||||
`tree-${storageKey}`,
|
||||
).then((response: any) => {
|
||||
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, storageKey])
|
||||
|
||||
// StateStoring fonksiyonlarını ref'e kaydet - Grid'deki gibi
|
||||
const customSaveStateRef = useRef(customSaveState)
|
||||
const customLoadStateRef = useRef(customLoadState)
|
||||
|
||||
useEffect(() => {
|
||||
customSaveStateRef.current = customSaveState
|
||||
customLoadStateRef.current = customLoadState
|
||||
}, [customSaveState, customLoadState])
|
||||
|
||||
useEffect(() => {
|
||||
if (gridRef?.current) {
|
||||
gridRef?.current?.instance().option('columns', undefined)
|
||||
|
|
@ -727,36 +738,58 @@ const Tree = (props: TreeProps) => {
|
|||
gridRef.current?.instance().refresh()
|
||||
}, [extraFilters])
|
||||
|
||||
useEffect(() => {
|
||||
if (!columnData || !gridRef?.current) return
|
||||
|
||||
const instance = gridRef?.current?.instance()
|
||||
if (instance) {
|
||||
instance.option('columns', columnData as any)
|
||||
}
|
||||
}, [columnData])
|
||||
|
||||
useEffect(() => {
|
||||
if (!treeListDataSource || !gridRef?.current) return
|
||||
|
||||
const instance = gridRef?.current?.instance()
|
||||
if (instance) {
|
||||
instance.option('dataSource', treeListDataSource)
|
||||
}
|
||||
}, [treeListDataSource])
|
||||
|
||||
useEffect(() => {
|
||||
refListFormCode.current = listFormCode
|
||||
if (!gridRef?.current) {
|
||||
return
|
||||
}
|
||||
}, [listFormCode])
|
||||
|
||||
gridRef?.current?.instance().option('columns', columnData as any)
|
||||
gridRef?.current?.instance().option('dataSource', treeListDataSource)
|
||||
// Component mount olduğunda state'i bir kez yükle
|
||||
useEffect(() => {
|
||||
if (!gridDto || !gridRef?.current || !treeListDataSource || !columnData) return
|
||||
|
||||
const stateStoring: IStateStoringProps = {
|
||||
enabled: gridDto?.gridOptions.stateStoringDto?.enabled,
|
||||
type: gridDto?.gridOptions.stateStoringDto?.type,
|
||||
savingTimeout: gridDto?.gridOptions.stateStoringDto?.savingTimeout,
|
||||
storageKey: gridDto?.gridOptions.stateStoringDto?.storageKey,
|
||||
const instance = gridRef?.current?.instance()
|
||||
if (instance) {
|
||||
customLoadState()
|
||||
.then((state) => {
|
||||
if (state) {
|
||||
instance.state(state)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('State load error:', err)
|
||||
})
|
||||
}
|
||||
if (
|
||||
gridDto?.gridOptions.stateStoringDto?.enabled &&
|
||||
gridDto?.gridOptions.stateStoringDto?.type === 'custom'
|
||||
) {
|
||||
// Ref pattern kullan - Grid'deki gibi
|
||||
stateStoring.customSave = (state: any) => customSaveStateRef.current(state)
|
||||
stateStoring.customLoad = () => customLoadStateRef.current()
|
||||
}
|
||||
gridRef?.current?.instance().option('stateStoring', stateStoring)
|
||||
}, [gridDto, treeListDataSource, columnData])
|
||||
|
||||
// State'i yükle - dataSource ve columns hazır olduğunda
|
||||
if (treeListDataSource && columnData) {
|
||||
gridRef?.current?.instance().state(undefined) // undefined = reload from storage
|
||||
// StateStoring'i devre dışı bırak - manuel kaydetme kullanılacak
|
||||
useEffect(() => {
|
||||
if (!gridDto || !gridRef?.current) return
|
||||
|
||||
const instance = gridRef?.current?.instance()
|
||||
if (instance) {
|
||||
// Otomatik state kaydetme/yükleme kapalı
|
||||
instance.option('stateStoring', {
|
||||
enabled: false,
|
||||
})
|
||||
}
|
||||
}, [columnData, treeListDataSource, gridDto]) // dataSource ve columns hazır olduğunda state yükle
|
||||
}, [gridDto])
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import {
|
|||
ListFormCustomizationForUserDto,
|
||||
ListFormCustomizationTypeEnum,
|
||||
} from '@/proxy/form/models'
|
||||
import { getListFormCustomization, postListFormCustomization } from '@/services/list-form-customization.service'
|
||||
import { getListFormCustomization } from '@/services/list-form-customization.service'
|
||||
import { useLocalization } from '@/utils/hooks/useLocalization'
|
||||
import { DataGridRef } from 'devextreme-react/data-grid'
|
||||
import { PivotGridRef } from 'devextreme-react/pivot-grid'
|
||||
|
|
@ -13,6 +13,7 @@ import { ToolbarItem } from 'devextreme/ui/data_grid_types'
|
|||
import dxDataGrid from 'devextreme/ui/data_grid'
|
||||
import dxPivotGrid from 'devextreme/ui/pivot_grid'
|
||||
import dxTreeList from 'devextreme/ui/tree_list'
|
||||
import dxGantt from 'devextreme/ui/gantt'
|
||||
import { Dispatch, MutableRefObject, SetStateAction, useEffect, useState } from 'react'
|
||||
import { setGridPanelColor } from './Utils'
|
||||
import { usePermission } from '@/utils/hooks/usePermission'
|
||||
|
|
@ -26,7 +27,7 @@ export interface ISelectBoxData {
|
|||
label?: string
|
||||
}
|
||||
|
||||
type GridInstance = dxDataGrid | dxPivotGrid | dxTreeList
|
||||
type GridInstance = dxDataGrid | dxPivotGrid | dxTreeList | dxGantt
|
||||
|
||||
// Grid tipini kontrol eden yardımcı fonksiyonlar
|
||||
const isDataGrid = (grid: GridInstance): grid is dxDataGrid => {
|
||||
|
|
@ -37,15 +38,12 @@ const isTreeList = (grid: GridInstance): grid is dxTreeList => {
|
|||
return 'getRootNode' in grid
|
||||
}
|
||||
|
||||
const getToolbarItems = (grid: GridInstance): any[] => {
|
||||
if (isDataGrid(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
return toolbarOptions?.items || []
|
||||
} else if (isTreeList(grid)) {
|
||||
const toolbarOptions = grid.option('toolbar')
|
||||
return toolbarOptions?.items || []
|
||||
}
|
||||
return []
|
||||
const isGantt = (grid: GridInstance): grid is dxGantt => {
|
||||
return 'getTaskData' in grid
|
||||
}
|
||||
|
||||
const supportsState = (grid: GridInstance): grid is dxDataGrid | dxTreeList => {
|
||||
return 'state' in grid && typeof (grid as any).state === 'function'
|
||||
}
|
||||
|
||||
const setToolbarItemValue = (grid: GridInstance, itemName: string, value: any) => {
|
||||
|
|
@ -140,6 +138,7 @@ const useFilters = ({
|
|||
gridDto,
|
||||
gridRef,
|
||||
listFormCode,
|
||||
saveGridState,
|
||||
}: {
|
||||
gridDto?: GridDto
|
||||
gridRef:
|
||||
|
|
@ -148,6 +147,7 @@ const useFilters = ({
|
|||
| MutableRefObject<TreeListRef<any, any> | undefined>
|
||||
| MutableRefObject<GanttRef | undefined>
|
||||
listFormCode: string
|
||||
saveGridState?: (state: any) => Promise<void>
|
||||
}): {
|
||||
filterToolbarData: ToolbarItem[]
|
||||
isCreateUpdateModalOpen: boolean
|
||||
|
|
@ -261,7 +261,7 @@ const useFilters = ({
|
|||
})
|
||||
}
|
||||
|
||||
if (checkPermission("App.Listforms.Listform.Update")) {
|
||||
if (checkPermission('App.Listforms.Listform.Update')) {
|
||||
menus.push({
|
||||
text: translate('::ListForms.ListForm.Manage'),
|
||||
id: 'openManage',
|
||||
|
|
@ -324,36 +324,12 @@ const useFilters = ({
|
|||
return
|
||||
}
|
||||
|
||||
const currentState = grid.state()
|
||||
const storageKey = gridDto?.gridOptions.stateStoringDto?.storageKey ?? ''
|
||||
|
||||
postListFormCustomization({
|
||||
listFormCode: listFormCode,
|
||||
customizationType: ListFormCustomizationTypeEnum.GridState,
|
||||
filterName: `list-${storageKey}`,
|
||||
customizationData: JSON.stringify(currentState),
|
||||
})
|
||||
.then(() => {
|
||||
setGridPanelColor(statedGridPanelColor)
|
||||
toast.push(
|
||||
<Notification type="success" duration={2000}>
|
||||
{translate('::ListForms.ListForm.GridStateSaved')}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
})
|
||||
.catch((err) => {
|
||||
toast.push(
|
||||
<Notification type="danger" duration={2500}>
|
||||
{translate('::ListForms.ListForm.GridStateSaveError')}
|
||||
</Notification>,
|
||||
{
|
||||
placement: 'top-end',
|
||||
},
|
||||
)
|
||||
if (saveGridState && supportsState(grid)) {
|
||||
const currentState = grid.state()
|
||||
saveGridState(currentState).catch(() => {
|
||||
// Error handling already done in customSaveState
|
||||
})
|
||||
}
|
||||
} else if (itemData.id === 'resetGridState') {
|
||||
// state ye kaydedilen grid ayarlarini siler ve gridi resetler
|
||||
const grid = gridRef.current?.instance()
|
||||
|
|
|
|||
Loading…
Reference in a new issue