Devexpress 25.1.7 versiyonuna convert edildi.

This commit is contained in:
Sedat ÖZTÜRK 2025-11-28 16:04:49 +03:00
parent 6b4e64c3ca
commit 1bf75e05fc
18 changed files with 695 additions and 609 deletions

View file

@ -20,7 +20,7 @@ public class GridColumnOptionDto
/// <summary> ilk kolon(lar) sabitlesitirlmesi ayari aktif mi /// <summary> ilk kolon(lar) sabitlesitirlmesi ayari aktif mi
/// </summary> /// </summary>
public bool ColumnFixingEnabled { get; set; } public bool ColumnFixingEnabled { get; set; } = false;
/// <summary> kolon secme butonu gosterilsin mi /// <summary> kolon secme butonu gosterilsin mi
/// </summary> /// </summary>
/// <summary> alabilecegi degerler: 'dragAndDrop', 'select' /// <summary> alabilecegi degerler: 'dragAndDrop', 'select'
@ -30,7 +30,7 @@ public class GridColumnOptionDto
/// </summary> /// </summary>
public bool HoverStateEnabled { get; set; } = false; public bool HoverStateEnabled { get; set; } = false;
public bool ColumnHidingEnabled { get; set; } = true; public bool ColumnHidingEnabled { get; set; } = true;
public bool FocusedRowEnabled { get; set; } = false; public bool FocusedRowEnabled { get; set; } = true;
public bool ShowColumnHeaders { get; set; } = true; public bool ShowColumnHeaders { get; set; } = true;
} }

View file

@ -54,12 +54,13 @@ public static class SeederDefaults
public static readonly string DefaultGroupPanelJson = JsonSerializer.Serialize(new { Visible = true }); public static readonly string DefaultGroupPanelJson = JsonSerializer.Serialize(new { Visible = true });
public static readonly string DefaultColumnOptionJson = JsonSerializer.Serialize(new public static readonly string DefaultColumnOptionJson = JsonSerializer.Serialize(new
{ {
ColumnFixingEnabled = true, ColumnFixingEnabled = false,
ColumnAutoWidth = true, ColumnAutoWidth = true,
ColumnChooserEnabled = true, ColumnChooserEnabled = true,
AllowColumnResizing = true, AllowColumnResizing = true,
AllowColumnReordering = true, AllowColumnReordering = true,
ColumnResizingMode = "widget", ColumnResizingMode = "widget",
FocusRowEnabled = true,
}); });
public static readonly string DefaultLayoutJson = JsonSerializer.Serialize(new LayoutDto() public static readonly string DefaultLayoutJson = JsonSerializer.Serialize(new LayoutDto()
{ {
@ -72,7 +73,7 @@ public static class SeederDefaults
}); });
public static readonly string DefaultSelectionSingleJson = JsonSerializer.Serialize(new SelectionDto public static readonly string DefaultSelectionSingleJson = JsonSerializer.Serialize(new SelectionDto
{ {
Mode = GridOptions.SelectionModeSingle, Mode = GridOptions.SelectionModeNone,
AllowSelectAll = false AllowSelectAll = false
}); });
public static readonly string DefaultSelectionMultipleJson = JsonSerializer.Serialize(new SelectionDto public static readonly string DefaultSelectionMultipleJson = JsonSerializer.Serialize(new SelectionDto

View file

@ -90,3 +90,48 @@ div.dialog-after-open > div.dialog-content.maximized {
min-width: fit-content !important; min-width: fit-content !important;
} }
/* React Pivot Vert Headers cok uzun olmaması icin */ /* React Pivot Vert Headers cok uzun olmaması icin */
/* Grid accessibility status mesajını gizle */
[e2e-a11y-general-status-container='true'] {
display: none !important;
visibility: hidden !important;
position: absolute !important;
left: -9999px !important;
}
/* Grid accessibility status mesajını gizle */
/* Grid Focused Row - Light Mode */
.dx-datagrid .dx-row-focused.dx-data-row > td:not(.dx-focused),
.dx-datagrid .dx-row-focused.dx-data-row > tr > td:not(.dx-focused) {
background-color: rgba(59, 130, 246, 0.15) !important;
color: inherit !important;
}
.dx-datagrid .dx-row-focused.dx-data-row .dx-link {
background-color: rgba(255, 255, 255, 0.5) !important;
border-radius: 4px !important;
color: #1e40af !important;
}
.dx-datagrid .dx-row-focused.dx-data-row .dx-link:hover {
background-color: rgba(255, 255, 255, 0.8) !important;
color: #1e3a8a !important;
}
/* Grid Focused Row - Dark Mode */
.dark .dx-datagrid .dx-row-focused.dx-data-row > td:not(.dx-focused),
.dark .dx-datagrid .dx-row-focused.dx-data-row > tr > td:not(.dx-focused) {
background-color: rgba(59, 130, 246, 0.25) !important;
color: #e5e7eb !important;
}
.dark .dx-datagrid .dx-row-focused.dx-data-row .dx-link {
background-color: rgba(0, 0, 0, 0.3) !important;
color: #93c5fd !important;
}
.dark .dx-datagrid .dx-row-focused.dx-data-row .dx-link:hover {
background-color: rgba(0, 0, 0, 0.5) !important;
color: #dbeafe !important;
}
/* Grid Focused Row */

View file

@ -217,8 +217,7 @@ const FormButtons = (props: {
if (onActionNew) { if (onActionNew) {
onActionNew() onActionNew()
} else { } else {
navigate(ROUTES_ENUM.protected.admin.formNew navigate(ROUTES_ENUM.protected.admin.formNew.replace(':listFormCode', listFormCode))
.replace(':listFormCode', listFormCode))
} }
}} }}
{...(permissions.c ? {} : { disabled: true })} {...(permissions.c ? {} : { disabled: true })}

View file

@ -1,6 +1,7 @@
import { DX_CLASSNAMES } from '@/constants/app.constant' import { DX_CLASSNAMES } from '@/constants/app.constant'
import { import {
Form as FormDx, Form as FormDx,
FormRef,
GroupItem as GroupItemDx, GroupItem as GroupItemDx,
Label as LabelDx, Label as LabelDx,
SimpleItem as SimpleItemDx, SimpleItem as SimpleItemDx,
@ -16,7 +17,7 @@ const FormDevExpress = (props: {
listFormCode: string listFormCode: string
isSubForm?: boolean isSubForm?: boolean
mode: RowMode mode: RowMode
refForm: RefObject<FormDx> refForm: RefObject<FormRef>
formData: any formData: any
formItems: GroupItem[] formItems: GroupItem[]
setFormData: Dispatch<any> setFormData: Dispatch<any>
@ -36,14 +37,14 @@ const FormDevExpress = (props: {
// formItems değiştiğinde (özellikle cascading alanlar için) editörlerin dataSource'larını güncelle // formItems değiştiğinde (özellikle cascading alanlar için) editörlerin dataSource'larını güncelle
useEffect(() => { useEffect(() => {
if (!refForm.current?.instance) return if (!refForm.current?.instance()) return
const allItems = formItems.flatMap((group) => (group.items as SimpleItemWithColData[]) || []) const allItems = formItems.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
allItems.forEach((item) => { allItems.forEach((item) => {
if (item.colData?.lookupDto?.dataSourceType && item.editorOptions?.dataSource) { if (item.colData?.lookupDto?.dataSourceType && item.editorOptions?.dataSource) {
try { try {
const editor = refForm.current?.instance.getEditor(item.dataField!) const editor = refForm.current?.instance().getEditor(item.dataField!)
if (editor) { if (editor) {
editor.option('dataSource', item.editorOptions.dataSource) editor.option('dataSource', item.editorOptions.dataSource)
} }
@ -57,7 +58,7 @@ const FormDevExpress = (props: {
// Cascade fieldlerin disabled durumunu güncelle // Cascade fieldlerin disabled durumunu güncelle
const updateCascadeDisabledStates = () => { const updateCascadeDisabledStates = () => {
if (!refForm.current?.instance) return if (!refForm.current?.instance()) return
const allItems = formItemsRef.current.flatMap((group) => (group.items as SimpleItemWithColData[]) || []) const allItems = formItemsRef.current.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
@ -67,7 +68,7 @@ const FormDevExpress = (props: {
const parentFields = cascadeParentFields.split(',').map((f: string) => f.trim()) const parentFields = cascadeParentFields.split(',').map((f: string) => f.trim())
try { try {
const editor = refForm.current?.instance.getEditor(item.dataField!) const editor = refForm.current?.instance().getEditor(item.dataField!)
if (editor && mode !== 'view') { if (editor && mode !== 'view') {
// Parent fieldlerden en az biri boşsa disabled olmalı // Parent fieldlerden en az biri boşsa disabled olmalı
const shouldDisable = parentFields.some((parentField: string) => { const shouldDisable = parentFields.some((parentField: string) => {

View file

@ -1,6 +1,6 @@
import { ColumnFormatDto, GridBoxOptionsDto } from '@/proxy/form/models' import { ColumnFormatDto, GridBoxOptionsDto } from '@/proxy/form/models'
import { Button } from 'devextreme-react/button' import { Button } from 'devextreme-react/button'
import DataGrid from 'devextreme-react/data-grid' import DataGrid, { DataGridRef } from 'devextreme-react/data-grid'
import DropDownBox from 'devextreme-react/drop-down-box' import DropDownBox from 'devextreme-react/drop-down-box'
import { ReactElement, useRef } from 'react' import { ReactElement, useRef } from 'react'
@ -19,7 +19,7 @@ const GridBoxEditorComponent = ({
col?: ColumnFormatDto col?: ColumnFormatDto
editorOptions: any editorOptions: any
}): ReactElement => { }): ReactElement => {
const gridRef = useRef<DataGrid>(null) const gridRef = useRef<DataGridRef>(null)
const val = Array.isArray(value) ? value : [value] const val = Array.isArray(value) ? value : [value]
const lookupDto = col?.lookupDto const lookupDto = col?.lookupDto
@ -43,7 +43,7 @@ const GridBoxEditorComponent = ({
//Eğer clear button kullanılırsa altında grid bilgileride otomatik deselect olmalı ve dropbox kapanmalı //Eğer clear button kullanılırsa altında grid bilgileride otomatik deselect olmalı ve dropbox kapanmalı
if (e.value === null) { if (e.value === null) {
e.component.close() e.component.close()
gridRef.current?.instance.deselectAll() gridRef.current?.instance().deselectAll()
} }
}} }}
contentRender={(e) => ( contentRender={(e) => (
@ -100,7 +100,7 @@ const GridBoxEditorComponent = ({
onClick={() => { onClick={() => {
e.component.option( e.component.option(
'value', 'value',
gridRef.current?.instance.getSelectedRowKeys().map((a: any) => a.key), gridRef.current?.instance().getSelectedRowKeys().map((a: any) => a.key),
) )
e.component.close() e.component.close()
}} }}

View file

@ -2,7 +2,7 @@ import { Notification, toast } from '@/components/ui'
import { getList } from '@/services/form.service' import { getList } from '@/services/form.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission' import { usePermission } from '@/utils/hooks/usePermission'
import { Form as FormDx } from 'devextreme-react/form' import { FormRef } from 'devextreme-react/form'
import { captionize } from 'devextreme/core/utils/inflector' import { captionize } from 'devextreme/core/utils/inflector'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { GroupItem } from 'devextreme/ui/form' import { GroupItem } from 'devextreme/ui/form'
@ -40,7 +40,7 @@ const useGridData = (props: {
const [formItems, setFormItems] = useState<GroupItem[]>([]) const [formItems, setFormItems] = useState<GroupItem[]>([])
const [permissionResults, setPermissionResults] = useState<PermissionResults>() const [permissionResults, setPermissionResults] = useState<PermissionResults>()
const refForm = useRef<FormDx>(null) const refForm = useRef<FormRef>(null)
const [searchParams] = useSearchParams() const [searchParams] = useSearchParams()
const navigate = useNavigate() const navigate = useNavigate()
const { translate } = useLocalization() const { translate } = useLocalization()
@ -84,7 +84,7 @@ const useGridData = (props: {
return return
} }
const validationResult = refForm.current?.instance.validate() const validationResult = refForm.current?.instance().validate()
if (!validationResult?.isValid) { if (!validationResult?.isValid) {
return return
} }

View file

@ -1,13 +1,8 @@
// src/.../useLookupDataSource.ts
import { dynamicFetch } from '@/services/form.service' import { dynamicFetch } from '@/services/form.service'
import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models' import { UiLookupDataSourceTypeEnum } from '@/proxy/form/models'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { useCallback } from 'react' import { useCallback } from 'react'
/** Module-scope cache: key -> Promise<array>
* - Aynı anda ılan editörler tek çağrısı üzerinden paylaşır
* - Hata olursa cache temizlenir (yeniden denenebilir)
*/
const __lookupCache = new Map<string, Promise<any[]>>() const __lookupCache = new Map<string, Promise<any[]>>()
const cachedLoader = (key: string, loader: () => Promise<any[]>) => { const cachedLoader = (key: string, loader: () => Promise<any[]>) => {

View file

@ -5,13 +5,13 @@ import { usePWA } from "@/utils/hooks/usePWA"
import CustomStore from "devextreme/data/custom_store" import CustomStore from "devextreme/data/custom_store"
import { useMemo, useRef, useState } from "react" import { useMemo, useRef, useState } from "react"
import { useNavigate } from "react-router-dom" import { useNavigate } from "react-router-dom"
import { Form as FormDx } from 'devextreme-react/form'
import { GroupItem } from 'devextreme/ui/form' import { GroupItem } from 'devextreme/ui/form'
import { PermissionResults, SimpleItemWithColData } from "../form/types" import { PermissionResults, SimpleItemWithColData } from "../form/types"
import { captionize } from 'devextreme/core/utils/inflector' import { captionize } from 'devextreme/core/utils/inflector'
import { ROUTES_ENUM } from "@/routes/route.constant" import { ROUTES_ENUM } from "@/routes/route.constant"
import FormButtons from "../form/FormButtons" import FormButtons from "../form/FormButtons"
import FormDevExpress from "../form/FormDevExpress" import FormDevExpress from "../form/FormDevExpress"
import { FormRef } from "devextreme-react/cjs/form"
const CardItem = ({ const CardItem = ({
isSubForm, isSubForm,
@ -31,7 +31,7 @@ const CardItem = ({
getCachedLookupDataSource: (editorOptions: any, colData: any, row?: any) => any getCachedLookupDataSource: (editorOptions: any, colData: any, row?: any) => any
}) => { }) => {
const [formData, setFormData] = useState(row) const [formData, setFormData] = useState(row)
const refForm = useRef<FormDx>(null) const refForm = useRef<FormRef>(null)
const navigate = useNavigate() const navigate = useNavigate()
const { translate } = useLocalization() const { translate } = useLocalization()
const { checkPermission } = usePermission() const { checkPermission } = usePermission()

View file

@ -12,7 +12,7 @@ import { usePermission } from '@/utils/hooks/usePermission'
import { Button, toast, Notification } from '@/components/ui' import { Button, toast, Notification } from '@/components/ui'
import { ROUTES_ENUM } from '@/routes/route.constant' import { ROUTES_ENUM } from '@/routes/route.constant'
import { usePWA } from '@/utils/hooks/usePWA' import { usePWA } from '@/utils/hooks/usePWA'
import { FaCog, FaCrosshairs, FaMinus, FaPlus, FaSearch, FaSyncAlt } from 'react-icons/fa' import { FaCog, FaCrosshairs, FaSearch, FaSyncAlt } from 'react-icons/fa'
import { buildSeriesDto } from './Utils' import { buildSeriesDto } from './Utils'
import { ChartSeriesDto } from '@/proxy/admin/charts/models' import { ChartSeriesDto } from '@/proxy/admin/charts/models'
import { SelectBoxOption } from '@/types/shared' import { SelectBoxOption } from '@/types/shared'

File diff suppressed because it is too large Load diff

View file

@ -3,7 +3,7 @@ import {
deleteListFormCustomization, deleteListFormCustomization,
postListFormCustomization, postListFormCustomization,
} from '@/services/list-form-customization.service' } from '@/services/list-form-customization.service'
import DataGrid from 'devextreme-react/data-grid' import { DataGridRef } from 'devextreme-react/data-grid'
import { Dispatch, MutableRefObject, SetStateAction, useState } from 'react' import { Dispatch, MutableRefObject, SetStateAction, useState } from 'react'
import CreatableSelect from 'react-select/creatable' import CreatableSelect from 'react-select/creatable'
import { ISelectBoxData } from './useFilters' import { ISelectBoxData } from './useFilters'
@ -11,7 +11,7 @@ import { ListFormCustomizationTypeEnum } from '@/proxy/form/models'
const GridFilterDialogs = (props: { const GridFilterDialogs = (props: {
listFormCode: string listFormCode: string
gridRef: MutableRefObject<DataGrid | undefined> gridRef: MutableRefObject<DataGridRef | undefined>
filtersForSelectBox: ISelectBoxData[] filtersForSelectBox: ISelectBoxData[]
isCreateUpdateModalOpen: boolean isCreateUpdateModalOpen: boolean
setIsCreateUpdateModalOpen: Dispatch<SetStateAction<boolean>> setIsCreateUpdateModalOpen: Dispatch<SetStateAction<boolean>>
@ -68,7 +68,7 @@ const GridFilterDialogs = (props: {
variant="solid" variant="solid"
disabled={!newFilterName || newFilterName === ''} disabled={!newFilterName || newFilterName === ''}
onClick={async () => { onClick={async () => {
const grid = gridRef.current?.instance // gridi al const grid = gridRef.current?.instance() // gridi al
if (!grid) { if (!grid) {
return return
} }
@ -141,7 +141,7 @@ const GridFilterDialogs = (props: {
variant="solid" variant="solid"
disabled={!newFilterId || newFilterId === ''} disabled={!newFilterId || newFilterId === ''}
onClick={async () => { onClick={async () => {
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (!grid || !newFilterId) { if (!grid || !newFilterId) {
return return
} }

View file

@ -1,4 +1,4 @@
import { useLocation, useParams, useSearchParams } from 'react-router-dom' import { useParams, useSearchParams } from 'react-router-dom'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import Container from '@/components/shared/Container' import Container from '@/components/shared/Container'
import Grid from './Grid' import Grid from './Grid'

View file

@ -6,15 +6,21 @@ import {
postListFormCustomization, postListFormCustomization,
} from '@/services/list-form-customization.service' } from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import Chart, { CommonSeriesSettings, Size, Tooltip } from 'devextreme-react/chart' import Chart, {
ChartRef,
CommonSeriesSettings,
Size,
Tooltip,
} from 'devextreme-react/chart'
import PivotGrid, { import PivotGrid, {
FieldChooser, FieldChooser,
FieldPanel, FieldPanel,
HeaderFilter, HeaderFilter,
IStateStoringProps, PivotGridRef,
PivotGridTypes, PivotGridTypes,
Scrolling, Scrolling,
Search, Search,
StateStoring,
} from 'devextreme-react/pivot-grid' } from 'devextreme-react/pivot-grid'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import PivotGridDataSource, { Field } from 'devextreme/ui/pivot_grid/data_source' import PivotGridDataSource, { Field } from 'devextreme/ui/pivot_grid/data_source'
@ -57,8 +63,8 @@ const Pivot = (props: PivotProps) => {
const { checkPermission } = usePermission() const { checkPermission } = usePermission()
const isPwaMode = usePWA() const isPwaMode = usePWA()
const gridRef = useRef<PivotGrid>() const gridRef = useRef<PivotGridRef>()
const chartRef = useRef<Chart>(null) const chartRef = useRef<ChartRef>(null)
const refListFormCode = useRef('') const refListFormCode = useRef('')
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>() const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
@ -113,7 +119,7 @@ const Pivot = (props: PivotProps) => {
} }
const clearPivotFilters = () => { const clearPivotFilters = () => {
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (!grid) return if (!grid) return
const ds = grid.getDataSource() const ds = grid.getDataSource()
@ -128,7 +134,7 @@ const Pivot = (props: PivotProps) => {
} }
const moveAllFieldsToFilterArea = () => { const moveAllFieldsToFilterArea = () => {
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (!grid) return if (!grid) return
const ds = grid.getDataSource() const ds = grid.getDataSource()
@ -136,7 +142,7 @@ const Pivot = (props: PivotProps) => {
const fields = ds.fields() const fields = ds.fields()
fields.forEach((field) => { fields.forEach((field: any) => {
field.area = 'filter' // tüm alanları filtre alanına taşı field.area = 'filter' // tüm alanları filtre alanına taşı
field.areaIndex = undefined field.areaIndex = undefined
}) })
@ -147,13 +153,13 @@ const Pivot = (props: PivotProps) => {
} }
const resetPivotGridState = async () => { const resetPivotGridState = async () => {
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (grid) { if (grid) {
// kullaniciya ait kayitli grid state i sil customizationData boşalt silinsin. // kullaniciya ait kayitli grid state i sil customizationData boşalt silinsin.
await postListFormCustomization({ await postListFormCustomization({
listFormCode: listFormCode, listFormCode: listFormCode,
customizationType: ListFormCustomizationTypeEnum.GridState, customizationType: ListFormCustomizationTypeEnum.GridState,
filterName: `pivot-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`, filterName: `pivot-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`,
customizationData: '', customizationData: '',
}) })
@ -164,38 +170,43 @@ const Pivot = (props: PivotProps) => {
} }
const customSaveState = useCallback( const customSaveState = useCallback(
(state: any) => (state: any) => {
postListFormCustomization({ return postListFormCustomization({
listFormCode: listFormCode, listFormCode: listFormCode,
customizationType: ListFormCustomizationTypeEnum.GridState, customizationType: ListFormCustomizationTypeEnum.GridState,
filterName: `pivot-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`, filterName: `pivot-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`,
customizationData: JSON.stringify(state), customizationData: JSON.stringify(state),
}).then(() => { }).then(() => {
setGridPanelColor(statedGridPanelColor) setGridPanelColor(statedGridPanelColor)
}), })
},
[listFormCode], [listFormCode],
) )
const customLoadState = useCallback( const customLoadState = useCallback(
() => () => {
getListFormCustomization( return getListFormCustomization(
listFormCode, listFormCode,
ListFormCustomizationTypeEnum.GridState, ListFormCustomizationTypeEnum.GridState,
`pivot-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`, `pivot-${gridRef.current?.instance()?.option('stateStoring')?.storageKey ?? ''}`,
).then((response: any) => { ).then((response: any) => {
setGridPanelColor(statedGridPanelColor) setGridPanelColor(statedGridPanelColor)
if (response.data?.length > 0) { if (response.data?.length > 0) {
return JSON.parse(response.data[0].customizationData) return JSON.parse(response.data[0].customizationData)
} }
}), })
},
[listFormCode], [listFormCode],
) )
useEffect(() => { useEffect(() => {
if (gridRef?.current) { if (gridRef?.current) {
gridRef.current.instance.option('remoteOperations', false) const instance = gridRef?.current?.instance()
gridRef.current.instance.option('dataSource', undefined) if (instance) {
gridRef.current.instance.option('stateStoring', undefined) instance.option('remoteOperations', false)
instance.option('dataSource', undefined)
instance.option('stateStoring', undefined)
}
} }
}, [listFormCode]) }, [listFormCode])
@ -269,30 +280,22 @@ const Pivot = (props: PivotProps) => {
fields, fields,
} }
gridRef.current.instance.option('dataSource', dataSource) const instance = gridRef?.current?.instance()
gridRef.current.instance.option('state', null) if (instance) {
instance.option('dataSource', dataSource)
const stateStoring: IStateStoringProps = { instance.option('state', null)
enabled: gridDto?.gridOptions.stateStoringDto?.enabled,
type: gridDto?.gridOptions.stateStoringDto?.type,
savingTimeout: gridDto?.gridOptions.stateStoringDto?.savingTimeout,
storageKey: gridDto?.gridOptions.stateStoringDto?.storageKey,
} }
if (
gridDto?.gridOptions.stateStoringDto?.enabled &&
gridDto?.gridOptions.stateStoringDto?.type === 'custom'
) {
stateStoring.customSave = customSaveState
stateStoring.customLoad = customLoadState
}
gridRef.current.instance.option('stateStoring', stateStoring)
//chart Integration //chart Integration
if (gridRef && chartRef) { if (gridRef?.current && chartRef?.current) {
gridRef?.current?.instance.bindChart(chartRef?.current?.instance, { const pivotInstance = gridRef?.current?.instance()
dataFieldsDisplayMode: 'splitPanes', const chartInstance = chartRef?.current?.instance()
alternateDataFields: false, if (pivotInstance && chartInstance) {
}) pivotInstance.bindChart(chartInstance, {
dataFieldsDisplayMode: 'splitPanes',
alternateDataFields: false,
})
}
} }
}, [columnData]) }, [columnData])
@ -400,6 +403,24 @@ const Pivot = (props: PivotProps) => {
enabled={gridDto.gridOptions.pivotOptionDto.columnChooserEnabled} enabled={gridDto.gridOptions.pivotOptionDto.columnChooserEnabled}
height={500} height={500}
/> />
<StateStoring
enabled={gridDto?.gridOptions.stateStoringDto?.enabled}
type={gridDto?.gridOptions.stateStoringDto?.type}
savingTimeout={gridDto?.gridOptions.stateStoringDto?.savingTimeout}
storageKey={gridDto?.gridOptions.stateStoringDto?.storageKey}
customSave={
gridDto?.gridOptions.stateStoringDto?.enabled &&
gridDto?.gridOptions.stateStoringDto?.type === 'custom'
? customSaveState
: undefined
}
customLoad={
gridDto?.gridOptions.stateStoringDto?.enabled &&
gridDto?.gridOptions.stateStoringDto?.type === 'custom'
? customLoadState
: undefined
}
/>
<Scrolling mode={gridDto.gridOptions.pagerOptionDto.scrollingMode} /> <Scrolling mode={gridDto.gridOptions.pagerOptionDto.scrollingMode} />
</PivotGrid> </PivotGrid>
</div> </div>

View file

@ -1,4 +1,3 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Container from '@/components/shared/Container' import Container from '@/components/shared/Container'
import { Dialog, Notification, toast } from '@/components/ui' import { Dialog, Notification, toast } from '@/components/ui'
import { DX_CLASSNAMES } from '@/constants/app.constant' import { DX_CLASSNAMES } from '@/constants/app.constant'
@ -34,6 +33,7 @@ import TreeListDx, {
Selection, Selection,
Sorting, Sorting,
Toolbar, Toolbar,
TreeListRef,
TreeListTypes, TreeListTypes,
} from 'devextreme-react/tree-list' } from 'devextreme-react/tree-list'
import { Item } from 'devextreme-react/toolbar' import { Item } from 'devextreme-react/toolbar'
@ -80,7 +80,7 @@ const Tree = (props: TreeProps) => {
const { translate } = useLocalization() const { translate } = useLocalization()
const { smaller } = useResponsive() const { smaller } = useResponsive()
const gridRef = useRef<TreeListDx>() const gridRef = useRef<TreeListRef>()
const refListFormCode = useRef('') const refListFormCode = useRef('')
const widgetGroupRef = useRef<HTMLDivElement>(null) const widgetGroupRef = useRef<HTMLDivElement>(null)
@ -166,7 +166,7 @@ const Tree = (props: TreeProps) => {
} }
async function getSelectedRowKeys() { async function getSelectedRowKeys() {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
if (!tree) { if (!tree) {
return [] return []
} }
@ -175,7 +175,7 @@ const Tree = (props: TreeProps) => {
} }
function getSelectedRowsData() { function getSelectedRowsData() {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
if (!tree) { if (!tree) {
return [] return []
} }
@ -184,7 +184,7 @@ const Tree = (props: TreeProps) => {
} }
function expandAll() { function expandAll() {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
if (!tree) return if (!tree) return
tree.forEachNode((node: any) => { tree.forEachNode((node: any) => {
if (node.hasChildren) { if (node.hasChildren) {
@ -194,7 +194,7 @@ const Tree = (props: TreeProps) => {
} }
function collapseAll() { function collapseAll() {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
if (!tree) return if (!tree) return
tree.forEachNode((node: any) => { tree.forEachNode((node: any) => {
if (node.hasChildren) { if (node.hasChildren) {
@ -204,11 +204,11 @@ const Tree = (props: TreeProps) => {
} }
function refreshData() { function refreshData() {
gridRef.current?.instance.refresh() gridRef.current?.instance().refresh()
} }
function getFilter() { function getFilter() {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
if (!tree) { if (!tree) {
return return
} }
@ -218,7 +218,7 @@ const Tree = (props: TreeProps) => {
function onSelectionChanged(data: any) { function onSelectionChanged(data: any) {
const treeOpt = gridDto?.gridOptions const treeOpt = gridDto?.gridOptions
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
if (!treeOpt || !tree) { if (!treeOpt || !tree) {
return return
} }
@ -536,7 +536,7 @@ const Tree = (props: TreeProps) => {
postListFormCustomization({ postListFormCustomization({
listFormCode: listFormCode, listFormCode: listFormCode,
customizationType: ListFormCustomizationTypeEnum.GridState, customizationType: ListFormCustomizationTypeEnum.GridState,
filterName: `tree-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`, filterName: `tree-${gridRef.current?.instance().option('stateStoring')?.storageKey ?? ''}`,
customizationData: JSON.stringify(state), customizationData: JSON.stringify(state),
}).then(() => { }).then(() => {
setGridPanelColor(statedGridPanelColor) setGridPanelColor(statedGridPanelColor)
@ -549,7 +549,7 @@ const Tree = (props: TreeProps) => {
getListFormCustomization( getListFormCustomization(
listFormCode, listFormCode,
ListFormCustomizationTypeEnum.GridState, ListFormCustomizationTypeEnum.GridState,
`tree-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`, `tree-${gridRef.current?.instance().option('stateStoring')?.storageKey ?? ''}`,
).then((response: any) => { ).then((response: any) => {
setGridPanelColor(statedGridPanelColor) setGridPanelColor(statedGridPanelColor)
if (response.data?.length > 0) { if (response.data?.length > 0) {
@ -561,9 +561,9 @@ const Tree = (props: TreeProps) => {
useEffect(() => { useEffect(() => {
if (gridRef?.current) { if (gridRef?.current) {
gridRef.current.instance.option('columns', undefined) gridRef?.current?.instance().option('columns', undefined)
gridRef.current.instance.option('dataSource', undefined) gridRef?.current?.instance().option('dataSource', undefined)
gridRef.current.instance.state(null) gridRef?.current?.instance().state(null)
} }
if (refListFormCode.current !== listFormCode) { if (refListFormCode.current !== listFormCode) {
@ -694,7 +694,7 @@ const Tree = (props: TreeProps) => {
searchParams?.delete('filter') searchParams?.delete('filter')
} }
gridRef.current?.instance.refresh() gridRef.current?.instance().refresh()
}, [extraFilters]) }, [extraFilters])
useEffect(() => { useEffect(() => {
@ -703,8 +703,8 @@ const Tree = (props: TreeProps) => {
return return
} }
gridRef.current.instance.option('columns', columnData as any) gridRef?.current?.instance().option('columns', columnData as any)
gridRef.current.instance.option('dataSource', treeListDataSource) gridRef?.current?.instance().option('dataSource', treeListDataSource)
const stateStoring: IStateStoringProps = { const stateStoring: IStateStoringProps = {
enabled: gridDto?.gridOptions.stateStoringDto?.enabled, enabled: gridDto?.gridOptions.stateStoringDto?.enabled,
@ -719,7 +719,7 @@ const Tree = (props: TreeProps) => {
stateStoring.customSave = customSaveState stateStoring.customSave = customSaveState
stateStoring.customLoad = customLoadState stateStoring.customLoad = customLoadState
} }
gridRef.current.instance.option('stateStoring', stateStoring) gridRef?.current?.instance().option('stateStoring', stateStoring)
}, [columnData]) }, [columnData])
return ( return (
@ -857,7 +857,7 @@ const Tree = (props: TreeProps) => {
text: translate('::Save'), text: translate('::Save'),
type: 'default', type: 'default',
onClick: () => { onClick: () => {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
tree?.saveEditData() tree?.saveEditData()
}, },
}, },
@ -869,7 +869,7 @@ const Tree = (props: TreeProps) => {
options: { options: {
text: translate('::Cancel'), text: translate('::Cancel'),
onClick: () => { onClick: () => {
const tree = gridRef.current?.instance const tree = gridRef.current?.instance()
tree?.cancelEditData() tree?.cancelEditData()
}, },
}, },

View file

@ -6,9 +6,9 @@ import {
} from '@/proxy/form/models' } from '@/proxy/form/models'
import { getListFormCustomization } from '@/services/list-form-customization.service' import { getListFormCustomization } from '@/services/list-form-customization.service'
import { useLocalization } from '@/utils/hooks/useLocalization' import { useLocalization } from '@/utils/hooks/useLocalization'
import DataGrid from 'devextreme-react/data-grid' import { DataGridRef } from 'devextreme-react/data-grid'
import PivotGrid from 'devextreme-react/pivot-grid' import { PivotGridRef } from 'devextreme-react/pivot-grid'
import TreeList from 'devextreme-react/tree-list' import { TreeListRef } from 'devextreme-react/tree-list'
import { ToolbarItem } from 'devextreme/ui/data_grid_types' import { ToolbarItem } from 'devextreme/ui/data_grid_types'
import dxDataGrid from 'devextreme/ui/data_grid' import dxDataGrid from 'devextreme/ui/data_grid'
import dxPivotGrid from 'devextreme/ui/pivot_grid' import dxPivotGrid from 'devextreme/ui/pivot_grid'
@ -141,9 +141,9 @@ const useFilters = ({
}: { }: {
gridDto?: GridDto gridDto?: GridDto
gridRef: gridRef:
| MutableRefObject<DataGrid<any, any> | undefined> | MutableRefObject<DataGridRef<any, any> | undefined>
| MutableRefObject<PivotGrid | undefined> | MutableRefObject<PivotGridRef | undefined>
| MutableRefObject<TreeList<any, any> | undefined> | MutableRefObject<TreeListRef<any, any> | undefined>
listFormCode: string listFormCode: string
}): { }): {
filterToolbarData: ToolbarItem[] filterToolbarData: ToolbarItem[]
@ -186,7 +186,7 @@ const useFilters = ({
}) ?? [] }) ?? []
setFiltersForSelectBox(mappedFilters) setFiltersForSelectBox(mappedFilters)
const grid = gridRef?.current?.instance const grid = gridRef?.current?.instance()
if (grid) { if (grid) {
setToolbarItemValue(grid, 'selectCustomFilters', '') setToolbarItemValue(grid, 'selectCustomFilters', '')
setToolbarItemItems(grid, 'selectCustomFilters', mappedFilters) setToolbarItemItems(grid, 'selectCustomFilters', mappedFilters)
@ -296,7 +296,7 @@ const useFilters = ({
) )
} else if (itemData.id === 'clearFilter') { } else if (itemData.id === 'clearFilter') {
// gridin bütün filtrelerini temizle // gridin bütün filtrelerini temizle
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (!grid) { if (!grid) {
return return
} }
@ -308,7 +308,7 @@ const useFilters = ({
setToolbarItemValue(grid, 'selectCustomFilters', '') setToolbarItemValue(grid, 'selectCustomFilters', '')
} else if (itemData.id === 'resetGridState') { } else if (itemData.id === 'resetGridState') {
// state ye kaydedilen grid ayarlarini siler ve gridi resetler // state ye kaydedilen grid ayarlarini siler ve gridi resetler
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (!grid) { if (!grid) {
return return
} }
@ -353,7 +353,7 @@ const useFilters = ({
onValueChanged(e: any) { onValueChanged(e: any) {
// gride seçili filtreyi uygula // gride seçili filtreyi uygula
let value: string | undefined let value: string | undefined
const grid = gridRef.current?.instance const grid = gridRef.current?.instance()
if (!grid) { if (!grid) {
return return
} }

View file

@ -305,18 +305,14 @@ const useListFormColumns = ({
return return
} }
const column = { const buttons: any[] = []
type: 'buttons',
width: 'auto',
buttons: [] as any,
}
if (hasUpdate) { if (hasUpdate) {
column.buttons.push('edit') buttons.push('edit')
} }
if (hasDelete) { if (hasDelete) {
column.buttons.push('delete') buttons.push('delete')
} }
gridDto.gridOptions.commandColumnDto.forEach((action) => { gridDto.gridOptions.commandColumnDto.forEach((action) => {
@ -365,8 +361,8 @@ const useListFormColumns = ({
props: dynamicMap, props: dynamicMap,
onClose: () => { onClose: () => {
// Dialog kapandığında grid'i yenile // Dialog kapandığında grid'i yenile
if (gridRef?.current?.instance) { if (gridRef?.current?.instance()) {
gridRef.current.instance.refresh() gridRef?.current?.instance().refresh()
} }
}, },
}) })
@ -377,9 +373,22 @@ const useListFormColumns = ({
}, },
} }
column.buttons.push(item) buttons.push(item)
}) })
// Buton sayısına göre dinamik genişlik hesapla
// Her buton için ~35-40px + padding
const calculatedWidth = Math.min(buttons.length * 40 + 30, 200)
const column = {
type: 'buttons',
width: calculatedWidth,
minWidth: calculatedWidth,
buttons,
cssClass: '[&_.dx-link]:mx-1',
allowResizing: true,
}
return column as GridColumnData return column as GridColumnData
} }

View file

@ -1,14 +1,14 @@
import DataGrid from 'devextreme-react/data-grid' import { DataGridRef } from 'devextreme-react/data-grid'
import PivotGrid from 'devextreme-react/pivot-grid' import { PivotGridRef } from 'devextreme-react/pivot-grid'
import CustomStore from 'devextreme/data/custom_store' import CustomStore from 'devextreme/data/custom_store'
import { MutableRefObject, useCallback } from 'react' import { MutableRefObject, useCallback } from 'react'
import { TreeList } from 'devextreme-react'
import { layoutTypes, ListViewLayoutType } from '@/views/admin/listForm/edit/types' import { layoutTypes, ListViewLayoutType } from '@/views/admin/listForm/edit/types'
import { getLoadOptions, getServiceAddress, setGridPanelColor } from './Utils' import { getLoadOptions, getServiceAddress, setGridPanelColor } from './Utils'
import { GridOptionsDto } from '@/proxy/form/models' import { GridOptionsDto } from '@/proxy/form/models'
import { GridColumnData } from './GridColumnData' import { GridColumnData } from './GridColumnData'
import { dynamicFetch } from '@/services/form.service' import { dynamicFetch } from '@/services/form.service'
import { MULTIVALUE_DELIMITER } from '@/constants/app.constant' import { MULTIVALUE_DELIMITER } from '@/constants/app.constant'
import { TreeListRef } from 'devextreme-react/cjs/tree-list'
const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk
@ -16,9 +16,9 @@ const useListFormCustomDataSource = ({
gridRef, gridRef,
}: { }: {
gridRef: gridRef:
| MutableRefObject<DataGrid<any, any> | undefined> | MutableRefObject<DataGridRef<any, any> | undefined>
| MutableRefObject<PivotGrid | undefined> | MutableRefObject<PivotGridRef | undefined>
| MutableRefObject<TreeList<any, any> | undefined> | MutableRefObject<TreeListRef<any, any> | undefined>
}) => { }) => {
const createSelectDataSource = useCallback( const createSelectDataSource = useCallback(
( (
@ -66,8 +66,8 @@ const useListFormCustomDataSource = ({
} }
// Type guard to handle union type for gridRef // Type guard to handle union type for gridRef
let columns = cols let columns = cols
if (gridRef?.current?.instance) { if (gridRef?.current?.instance()) {
const instance = gridRef.current.instance as any const instance = gridRef?.current?.instance() as any
const instanceColumns = instance.option('columns') const instanceColumns = instance.option('columns')
if (instanceColumns) { if (instanceColumns) {
columns = instanceColumns as GridColumnData[] columns = instanceColumns as GridColumnData[]
@ -157,6 +157,7 @@ const useListFormCustomDataSource = ({
summary: response.data.summary, summary: response.data.summary,
groupCount: response.data.groupCount, groupCount: response.data.groupCount,
} }
return retValue return retValue
} catch (error: any) { } catch (error: any) {
// toast.push( // toast.push(