erp-platform/ui/src/views/list/Grid.tsx

764 lines
29 KiB
TypeScript
Raw Normal View History

2025-05-06 06:45:49 +00:00
/* eslint-disable @typescript-eslint/no-explicit-any */
import Container from '@/components/shared/Container'
import { Dialog, Notification, toast } from '@/components/ui'
import { DX_CLASSNAMES } from '@/constants/app.constant'
import {
DbTypeEnum,
EditingFormItemDto,
GridDto,
ListFormCustomizationTypeEnum,
PlatformEditorTypes,
} from '@/proxy/form'
import { getList } from '@/proxy/form/form.service'
import {
getListFormCustomization,
postListFormCustomization,
} from '@/proxy/form/list-form-customization.service'
import { useListFormColumns } from '@/shared/useListFormColumns'
import { useListFormCustomDataSource } from '@/shared/useListFormCustomDataSource'
import { useLocalization } from '@/utils/hooks/useLocalization'
import useResponsive from '@/utils/hooks/useResponsive'
import { Template } from 'devextreme-react/core/template'
import DataGrid, {
ColumnChooser,
ColumnFixing,
DataGridTypes,
Editing,
Export,
FilterPanel,
FilterRow,
Grouping,
GroupItem as GroupItemDx,
GroupPanel,
HeaderFilter,
IStateStoringProps,
LoadPanel,
Pager,
Scrolling,
SearchPanel,
Selection,
Sorting,
Summary,
Toolbar,
TotalItem,
} from 'devextreme-react/data-grid'
import { Item } from 'devextreme-react/toolbar'
import { DataType } from 'devextreme/common'
import { captionize } from 'devextreme/core/utils/inflector'
import CustomStore from 'devextreme/data/custom_store'
import { GroupItem } from 'devextreme/ui/form'
import { useCallback, useEffect, useRef, useState } from 'react'
import { Helmet } from 'react-helmet'
import SubForms from '../form/SubForms'
import { RowMode, SimpleItemWithColData } from '../form/types'
import { GridColumnData } from './GridColumnData'
import GridFilterDialogs from './GridFilterDialogs'
import {
addCss,
addJs,
controlStyleCondition,
setFormEditingExtraItemValues,
setGridPanelColor,
} from './Utils'
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent'
import { useFilters } from './useFilters'
import { useToolbar } from './useToolbar'
import { Workbook } from 'exceljs';
import saveAs from 'file-saver';
import { jsPDF } from 'jspdf'
import { exportDataGrid as exportDataPdf } from 'devextreme/pdf_exporter';
import { exportDataGrid as exportDataExcel } from 'devextreme/excel_exporter'
interface GridProps {
listFormCode: string
searchParams?: URLSearchParams
isSubForm?: boolean
level?: number
refreshData?: () => Promise<void>
}
const statedGridPanelColor = 'rgba(50, 200, 200, 0.5)' // kullanici tanimli gridState ile islem gormus gridin paneline ait renk
const Grid = (props: GridProps) => {
const { listFormCode, searchParams, isSubForm, level } = props
const { translate } = useLocalization()
const { smaller } = useResponsive()
const gridRef = useRef<DataGrid>()
const refListFormCode = useRef('')
const [gridDto, setGridDto] = useState<GridDto>()
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
const [columnData, setColumnData] = useState<GridColumnData[]>()
const [formData, setFormData] = useState<any>()
const [mode, setMode] = useState<RowMode>('view')
const { toolbarData, toolbarModalData, setToolbarModalData } = useToolbar({
gridDto,
listFormCode,
getSelectedRowKeys,
getSelectedRowsData,
refreshData,
getFilter,
})
const { filterToolbarData, ...filterData } = useFilters({
gridDto,
gridRef,
listFormCode,
})
const { createSelectDataSource } = useListFormCustomDataSource({ gridRef })
const { getBandedColumns } = useListFormColumns({
gridDto,
listFormCode,
isSubForm,
})
async function getSelectedRowKeys() {
const grd = gridRef.current?.instance
if (!grd) {
return []
}
return await grd.getSelectedRowKeys()
}
function getSelectedRowsData() {
const grd = gridRef.current?.instance
if (!grd) {
return []
}
return grd.getSelectedRowsData()
}
function refreshData() {
gridRef.current?.instance.refresh()
}
function getFilter() {
const grd = gridRef.current?.instance
if (!grd) {
return
}
return grd.getCombinedFilter()
}
function onSelectionChanged(data: any) {
const grdOpt = gridDto?.gridOptions
const grd = gridRef.current?.instance
if (!grdOpt || !grd) {
return
}
// kullanicinin yetkisi varsa ve birden fazla kayit secili ise coklu silme gorunsun
if (grdOpt.editingOptionDto?.allowDeleting) {
// && abp.auth.isGranted(grdOpt.permissionDto?.d)
// kullanicinin silme yetkisi var ise
const opt = grd.option('toolbar')
const deleteSelectedRecordsIndex = opt?.items
?.map((e: any) => e.name)
.indexOf('deleteSelectedRecords')
// deleteSelectedRecords ismindeki custom butonun index degerini bul
grd.option(
`toolbar.items[${deleteSelectedRecordsIndex}].options.visible`,
data.selectedRowsData.length > 1,
) // birden fazla kayit secilmis ise gorunsun
}
// SubForm'ları gösterebilmek için secili satiri formData'ya at
if (data.selectedRowsData.length) {
setFormData(data.selectedRowsData[0])
}
}
function onCellPrepared(e: any) {
const columnFormats = gridDto?.columnFormats
if (!columnFormats) {
return
}
// satir, hucre yada header vb. kisimlara conditional style uygulamak icin
for (let indxCol = 0; indxCol < columnFormats.length; indxCol++) {
const colFormat = columnFormats[indxCol]
for (let indxStyl = 0; indxStyl < colFormat.columnStylingDto.length; indxStyl++) {
const colStyle = colFormat.columnStylingDto[indxStyl] // uygulanacak style
if (e.rowType == colStyle.rowType) {
// header, filter, data, group, summaries ..her birisine style uygulanabilir
// style bütün satıra uygulansın olarak seçili ise yada sadece ilgili field üzerinde ise
if (colStyle.useRow || e.column.dataField == colFormat.fieldName) {
if (
!colStyle.conditionValue ||
controlStyleCondition(e.data, colFormat.fieldName, colStyle)
) {
// css sınıf ismi var ise uygula
if (colStyle.cssClassName) {
e.cellElement.addClass(colStyle.cssClassName)
}
// css inline style var ise uygula
if (colStyle.cssStyles) {
e.cellElement.attr('style', e.cellElement.attr('style') + ';' + colStyle.cssStyles)
}
}
}
}
}
}
}
function onInitNewRow(e: any) {
if (!gridDto?.columnFormats) {
return
}
setMode('new')
for (const colFormat of gridDto?.columnFormats) {
if (!colFormat.fieldName) {
continue
}
// Grid'den gelen columnFormat'ları kullanarak default değerleri set et
if (colFormat.defaultValue != null) {
e.data[colFormat.fieldName] = colFormat.defaultValue
}
// URL'den veya Component Prop'dan gelen parametreleri set et
if (!searchParams) {
continue
}
if (searchParams.has(colFormat.fieldName)) {
const dType = colFormat.dataType as DataType
switch (dType) {
case 'date':
case 'datetime':
e.data[colFormat.fieldName] = new Date(searchParams.get(colFormat.fieldName)!)
break
case 'number':
e.data[colFormat.fieldName] = Number(searchParams.get(colFormat.fieldName))
break
case 'boolean':
if (searchParams.get(colFormat.fieldName) === 'true') {
e.data[colFormat.fieldName] = true
} else if (searchParams.get(colFormat.fieldName) === 'false') {
e.data[colFormat.fieldName] = false
}
break
case 'object':
try {
e.data[colFormat.fieldName] = JSON.parse(
searchParams.get(colFormat.fieldName) as string,
)
} catch (error) {}
break
default:
e.data[colFormat.fieldName] = searchParams.get(colFormat.fieldName)
break
}
}
}
}
function onRowInserting(e: DataGridTypes.RowInsertingEvent<any, any>) {
e.data = setFormEditingExtraItemValues(e.data)
}
function onRowUpdating(e: DataGridTypes.RowUpdatingEvent<any, any>) {
if (gridDto?.gridOptions.editingOptionDto?.sendOnlyChangedFormValuesUpdate) {
if (Object.keys(e.newData).some((a) => a.includes(':'))) {
Object.keys(e.oldData).forEach((col) => {
if (col.includes(':')) {
e.newData[col] = e.newData[col] ?? e.oldData[col]
}
})
}
e.newData = setFormEditingExtraItemValues(e.newData)
} else {
let newData = { ...e.oldData, ...e.newData }
newData = setFormEditingExtraItemValues(newData)
Object.keys(newData).forEach((key) => {
if (key.includes(':')) {
delete newData[key]
}
})
e.newData = newData
}
if (gridDto?.gridOptions.keyFieldName) {
delete e.newData[gridDto?.gridOptions.keyFieldName]
}
}
function onEditingStart(e: DataGridTypes.EditingStartEvent<any, any>) {
setMode('edit')
const columns = e.component.option('columns') as GridColumnData[]
// FormEditingExtraItem field ise datayı doldur
columns?.forEach((col) => {
if (!col.dataField?.includes(':')) {
return
}
const field = col.dataField.split(':')
if (!e.data[field[0]]) {
return
}
const json = JSON.parse(e.data[field[0]])
e.data[col.dataField] = json[field[1]]
})
}
function onDataErrorOccurred(e: DataGridTypes.DataErrorOccurredEvent<any, any>) {
toast.push(
<Notification type="danger" duration={2000}>
{e.error?.message}
</Notification>,
{
placement: 'top-center',
},
)
}
const customSaveState = useCallback(
(state: any) =>
postListFormCustomization({
listFormCode: listFormCode,
customizationType: ListFormCustomizationTypeEnum.GridState,
filterName: `list-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`,
customizationData: JSON.stringify(state),
}).then(() => {
setGridPanelColor(statedGridPanelColor)
}),
[listFormCode],
)
const customLoadState = useCallback(
() =>
getListFormCustomization(
listFormCode,
ListFormCustomizationTypeEnum.GridState,
`list-${gridRef.current?.instance.option('stateStoring')?.storageKey ?? ''}`,
).then((response: any) => {
setGridPanelColor(statedGridPanelColor)
if (response.data?.length > 0) {
return JSON.parse(response.data[0].customizationData)
}
}),
[listFormCode],
)
useEffect(() => {
if (gridRef?.current) {
gridRef.current.instance.option('columns', undefined)
gridRef.current.instance.option('remoteOperations', false)
gridRef.current.instance.option('dataSource', undefined)
gridRef.current.instance.state(null)
}
const initializeGrid = async () => {
const response = await getList({ listFormCode })
setGridDto(response.data)
}
if (refListFormCode.current !== listFormCode) {
initializeGrid()
}
}, [listFormCode])
useEffect(() => {
if (!gridDto) {
return
}
// Set js and css
const grdOpt = gridDto.gridOptions
if (grdOpt.customJsSources.length) {
for (const js of grdOpt.customJsSources) {
addJs(js)
}
}
if (grdOpt.customStyleSources.length) {
for (const css of grdOpt.customStyleSources) {
addCss(css)
}
}
}, [gridDto])
useEffect(() => {
if (!gridDto) {
return
}
// Set columns
const cols = getBandedColumns()
setColumnData(cols)
// Set data source
const dataSource: CustomStore<any, any> = createSelectDataSource(
gridDto.gridOptions,
listFormCode,
searchParams,
cols,
)
setGridDataSource(dataSource)
}, [gridDto, searchParams])
useEffect(() => {
refListFormCode.current = listFormCode
if (!gridRef?.current) {
return
}
gridRef.current.instance.option('remoteOperations', { groupPaging: true })
gridRef.current.instance.option('columns', columnData)
gridRef.current.instance.option('dataSource', gridDataSource)
const stateStoring: IStateStoringProps = {
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)
}, [columnData])
const onExporting = (e: DataGridTypes.ExportingEvent) => {
if(e.format == 'xlsx') {
const workbook = new Workbook()
const worksheet = workbook.addWorksheet(`${listFormCode}_sheet`)
exportDataExcel({
component: gridRef?.current?.instance,
worksheet,
autoFilterEnabled: true,
}).then(() => {
workbook.xlsx.writeBuffer().then((buffer) => {
saveAs(new Blob([buffer], { type: 'application/octet-stream' }), `${listFormCode}_export.xlsx`)
})
})
} else if(e.format == 'pdf') {
const doc = new jsPDF()
exportDataPdf({
jsPDFDocument: doc,
component: gridRef?.current?.instance,
indent: 5,
}).then(() => {
doc.save(`${listFormCode}_export.pdf`)
})
} else if (e.format == 'csv') {
const workbook = new Workbook();
const worksheet = workbook.addWorksheet(`${listFormCode}_sheet`)
exportDataExcel({
component: gridRef?.current?.instance,
worksheet: worksheet
}).then(function() {
workbook.csv.writeBuffer().then(function(buffer) {
saveAs(new Blob([buffer], { type: "application/octet-stream" }), `${listFormCode}_export.csv`)
})
})
}
};
return (
<Container className={DX_CLASSNAMES}>
{!isSubForm && (
<Helmet
2025-05-06 08:04:37 +00:00
titleTemplate="%s | KursPlatform"
2025-05-06 06:45:49 +00:00
title={translate('::' + gridDto?.gridOptions.title)}
2025-05-06 08:04:37 +00:00
defaultTitle="KursPlatform"
2025-05-06 06:45:49 +00:00
></Helmet>
)}
{gridDto && columnData && (
<>
<DataGrid
ref={gridRef as any}
id={'Grid-' + listFormCode}
//dataSource={gridDataSource}
//remoteOperations={{ groupPaging: true }}
//remoteOperations={false}
height={gridDto.gridOptions.height || '100%'}
width={gridDto.gridOptions.width || '100%'}
allowColumnResizing={gridDto.gridOptions.columnOptionDto?.allowColumnResizing}
allowColumnReordering={gridDto.gridOptions.columnOptionDto?.allowColumnReordering}
showBorders={gridDto.gridOptions.columnOptionDto?.showBorders}
showRowLines={gridDto.gridOptions.columnOptionDto?.showRowLines}
showColumnLines={gridDto.gridOptions.columnOptionDto?.showColumnLines}
columnResizingMode={gridDto.gridOptions.columnOptionDto?.columnResizingMode}
columnAutoWidth={gridDto.gridOptions.columnOptionDto?.columnAutoWidth}
rtlEnabled={gridDto.gridOptions.columnOptionDto?.rtlEnabled}
rowAlternationEnabled={gridDto.gridOptions.columnOptionDto?.rowAlternationEnabled}
hoverStateEnabled={gridDto.gridOptions.columnOptionDto?.hoverStateEnabled}
columnHidingEnabled={gridDto.gridOptions.columnOptionDto?.columnHidingEnabled}
focusedRowEnabled={gridDto.gridOptions.columnOptionDto?.focusedRowEnabled}
showColumnHeaders={gridDto.gridOptions.columnOptionDto?.showColumnHeaders}
filterSyncEnabled={true}
onSelectionChanged={onSelectionChanged}
onInitNewRow={onInitNewRow}
onCellPrepared={onCellPrepared}
onRowInserting={onRowInserting}
onRowUpdating={onRowUpdating}
onEditingStart={onEditingStart}
onDataErrorOccurred={onDataErrorOccurred}
onExporting={onExporting}
onEditCanceled={() => {
setMode('view')
}}
onSaved={() => {
setMode('view')
}}
onRowInserted={() => {
props.refreshData?.()
}}
onRowUpdated={() => {
props.refreshData?.()
}}
onRowRemoved={() => {
props.refreshData?.()
}}
>
<Export enabled={true} allowExportSelectedData={false} formats={['pdf', 'xlsx', 'csv']} />
<Editing
refreshMode={gridDto.gridOptions.editingOptionDto?.refreshMode}
mode={smaller.md ? 'form' : gridDto.gridOptions.editingOptionDto?.mode}
allowDeleting={gridDto.gridOptions.editingOptionDto?.allowDeleting}
allowUpdating={gridDto.gridOptions.editingOptionDto?.allowUpdating}
allowAdding={gridDto.gridOptions.editingOptionDto?.allowAdding}
useIcons={gridDto.gridOptions.editingOptionDto?.useIcons}
confirmDelete={gridDto.gridOptions.editingOptionDto?.confirmDelete}
newRowPosition={gridDto.gridOptions.editingOptionDto?.newRowPosition}
selectTextOnEditStart={gridDto.gridOptions.editingOptionDto?.selectTextOnEditStart}
startEditAction={gridDto.gridOptions.editingOptionDto?.startEditAction}
popup={{
title: gridDto.gridOptions.editingOptionDto?.popup?.title,
showTitle: gridDto.gridOptions.editingOptionDto?.popup?.showTitle,
hideOnOutsideClick: gridDto.gridOptions.editingOptionDto?.popup?.hideOnOutsideClick,
width: gridDto.gridOptions.editingOptionDto?.popup?.width,
height: gridDto.gridOptions.editingOptionDto?.popup?.height,
fullScreen: gridDto.gridOptions.editingOptionDto?.popup?.fullScreen,
}}
form={{
items:
gridDto.gridOptions.editingFormDto?.length > 0
? gridDto.gridOptions.editingFormDto
?.sort((a, b) => {
return a.order >= b.order ? 1 : -1
})
.map((e) => {
return {
itemType: e.itemType,
colCount: e.colCount,
colSpan: e.colSpan,
caption: e.caption,
items: e.items
?.sort((a, b) => {
return a.order >= b.order ? 1 : -1
})
.map((i: EditingFormItemDto) => {
let editorOptions = {}
try {
editorOptions = i.editorOptions && JSON.parse(i.editorOptions)
// Eğer default value varsa, bu editörü readonly yapıyoruz
if (searchParams?.has(i.dataField)) {
editorOptions = {
...editorOptions,
readOnly: true,
}
}
} catch {}
const fieldName = i.dataField.split(':')[0]
const listFormField = gridDto.columnFormats.find(
(x) => 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,
}
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
})
.filter((a) => {
// return a.canRead
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
}
}),
} as GroupItem
})
: undefined,
}}
></Editing>
<Template name={'cellEditTagBox'} render={TagBoxEditorComponent} />
<Template name={'cellEditGridBox'} render={GridBoxEditorComponent} />
<Toolbar visible={toolbarData.length > 0 || filterToolbarData.length > 0}>
{toolbarData.map((item) => (
<Item key={item.name} {...item}></Item>
))}
{filterToolbarData.map((item) => (
<Item key={item.name} {...item}></Item>
))}
</Toolbar>
<Sorting mode={gridDto.gridOptions?.sortMode}></Sorting>
<FilterRow
visible={gridDto.gridOptions.filterRowDto?.visible}
applyFilter={gridDto.gridOptions.filterRowDto?.applyFilter}
></FilterRow>
<FilterPanel visible={gridDto.gridOptions.filterPanelDto.visible}></FilterPanel>
<HeaderFilter visible={gridDto.gridOptions.headerFilterDto.visible}></HeaderFilter>
<SearchPanel
visible={gridDto.gridOptions.searchPanelDto.visible}
width={gridDto.gridOptions.searchPanelDto.width}
></SearchPanel>
<GroupPanel visible={gridDto.gridOptions.groupPanelDto?.visible}></GroupPanel>
<Grouping autoExpandAll={gridDto.gridOptions.groupPanelDto?.autoExpandAll}></Grouping>
<Selection
mode={gridDto.gridOptions.selectionDto?.mode}
allowSelectAll={gridDto.gridOptions.selectionDto?.allowSelectAll}
selectAllMode={gridDto.gridOptions.selectionDto?.selectAllMode}
showCheckBoxesMode={gridDto.gridOptions.selectionDto?.showCheckBoxesMode}
></Selection>
{/* <Paging pageSize={gridDto.gridOptions.pageSize ?? 0}></Paging> */}
<Pager
visible={gridDto.gridOptions.pagerOptionDto?.visible}
allowedPageSizes={gridDto.gridOptions.pagerOptionDto?.allowedPageSizes
?.split(',')
.map((a) => +a)}
showPageSizeSelector={gridDto.gridOptions.pagerOptionDto?.showPageSizeSelector}
showInfo={gridDto.gridOptions.pagerOptionDto?.showInfo}
showNavigationButtons={gridDto.gridOptions.pagerOptionDto?.showNavigationButtons}
infoText={gridDto.gridOptions.pagerOptionDto?.infoText}
displayMode={gridDto.gridOptions.pagerOptionDto?.displayMode}
></Pager>
<ColumnChooser
enabled={gridDto.gridOptions.columnOptionDto?.columnChooserEnabled}
mode={gridDto.gridOptions.columnOptionDto?.columnChooserMode}
></ColumnChooser>
<ColumnFixing
enabled={gridDto.gridOptions.columnOptionDto?.columnFixingEnabled}
></ColumnFixing>
<Scrolling mode={gridDto.gridOptions.pagerOptionDto?.scrollingMode}></Scrolling>
<LoadPanel
enabled={gridDto.gridOptions.pagerOptionDto?.loadPanelEnabled}
text={gridDto.gridOptions.pagerOptionDto?.loadPanelText}
></LoadPanel>
<Summary>
{gridDto.columnFormats
.filter((x) => !!x.columnTotalSummaryDto?.summaryType)
.map((x) => (
<TotalItem
key={`Total_${x.fieldName}`}
column={x.fieldName}
summaryType={x.columnTotalSummaryDto.summaryType as any}
showInColumn={x.columnTotalSummaryDto.showInColumn}
valueFormat={x.columnTotalSummaryDto.valueFormat}
displayFormat={x.columnTotalSummaryDto.displayFormat}
/>
))}
{gridDto.columnFormats
.filter((x) => !!x.columnGroupSummaryDto?.summaryType)
.map((x) => (
<GroupItemDx
key={`Group_${x.fieldName}`}
column={x.fieldName}
summaryType={x.columnGroupSummaryDto.summaryType as any}
showInColumn={x.columnGroupSummaryDto.showInColumn}
valueFormat={x.columnGroupSummaryDto.valueFormat}
displayFormat={x.columnGroupSummaryDto.displayFormat}
/>
))}
</Summary>
{/* <Column
dataField="Quantity"
width={160}
alignment="right"
//format={'0.000'}
//format="fixedPoint"
editorOptions={{ type: 'fixedPoint', pricision: 1 }}
>
<Format type="fixedPoint" precision={2} />
</Column> */}
</DataGrid>
{gridDto?.gridOptions?.subFormsDto?.length > 0 && (
<>
<hr className="my-4" />
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} />
</>
)}
</>
)}
<Dialog
isOpen={toolbarModalData?.open || false}
onClose={() => setToolbarModalData(undefined)}
onRequestClose={() => setToolbarModalData(undefined)}
>
{toolbarModalData?.content}
</Dialog>
<GridFilterDialogs gridRef={gridRef} listFormCode={listFormCode} {...filterData} />
</Container>
)
}
export default Grid