FormView, FormNew, Grid Popup için Script özelliği eklendi. Ayrıca itemlara buton eklenebiliyor. Sadece textbox olan inputlara ekleniyor. Diğer komponenler için render özelliği kullanılması gerekiyor.
1066 lines
42 KiB
TypeScript
1066 lines
42 KiB
TypeScript
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/models'
|
||
import {
|
||
getListFormCustomization,
|
||
postListFormCustomization,
|
||
} from '@/services/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,
|
||
GridExtraFilterState,
|
||
setFormEditingExtraItemValues,
|
||
setGridPanelColor,
|
||
} from './Utils'
|
||
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
|
||
import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent'
|
||
import { useFilters } from './useFilters'
|
||
import { useToolbar } from './useToolbar'
|
||
import { ImportDashboard } from '@/components/importManager/ImportDashboard'
|
||
import WidgetGroup from '@/components/ui/Widget/WidgetGroup'
|
||
import { GridExtraFilterToolbar } from './GridExtraFilterToolbar'
|
||
import { getList } from '@/services/form.service'
|
||
|
||
interface GridProps {
|
||
listFormCode: string
|
||
searchParams?: URLSearchParams
|
||
isSubForm?: boolean
|
||
level?: number
|
||
refreshData?: () => Promise<void>
|
||
gridDto?: GridDto
|
||
}
|
||
|
||
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, gridDto: extGridDto } = props
|
||
const { translate } = useLocalization()
|
||
const { smaller } = useResponsive()
|
||
|
||
const gridRef = useRef<DataGrid>()
|
||
const refListFormCode = useRef('')
|
||
|
||
const [gridDataSource, setGridDataSource] = useState<CustomStore<any, any>>()
|
||
const [columnData, setColumnData] = useState<GridColumnData[]>()
|
||
const [formData, setFormData] = useState<any>()
|
||
const [mode, setMode] = useState<RowMode>('view')
|
||
const [extraFilters, setExtraFilters] = useState<GridExtraFilterState[]>([])
|
||
const [gridDto, setGridDto] = useState<GridDto>()
|
||
|
||
const preloadExportLibs = () => {
|
||
import('exceljs')
|
||
import('file-saver')
|
||
import('devextreme/excel_exporter')
|
||
import('jspdf')
|
||
import('devextreme/pdf_exporter')
|
||
}
|
||
|
||
type EditorOptionsWithButtons = {
|
||
buttons?: any[]
|
||
} & Record<string, any>
|
||
|
||
const defaultSearchParams = useRef<string | null>(null)
|
||
|
||
useEffect(() => {
|
||
const initializeGrid = async () => {
|
||
const response = await getList({ listFormCode })
|
||
setGridDto(response.data)
|
||
}
|
||
|
||
if (extGridDto === undefined) {
|
||
initializeGrid()
|
||
} else {
|
||
setGridDto(extGridDto)
|
||
}
|
||
}, [listFormCode, extGridDto])
|
||
|
||
useEffect(() => {
|
||
if (!defaultSearchParams.current) {
|
||
defaultSearchParams.current = searchParams?.get('filter') ?? null
|
||
}
|
||
}, [searchParams])
|
||
|
||
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,
|
||
})
|
||
|
||
function extractSearchParamsFields(filter: any): [string, string, any][] {
|
||
if (!Array.isArray(filter)) return []
|
||
|
||
// [field, op, val] formu mu?
|
||
if (filter.length === 3 && typeof filter[0] === 'string') {
|
||
return [filter as [string, string, any]]
|
||
}
|
||
|
||
// içinde başka filter array’leri olabilir
|
||
return filter.flatMap((f) => extractSearchParamsFields(f))
|
||
}
|
||
|
||
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
|
||
}
|
||
|
||
// ExtraFilters içerisinde ilgili Field varsa, default değerleri set etme
|
||
if (extraFilters.some((f) => f.fieldName === colFormat.fieldName)) {
|
||
continue
|
||
}
|
||
|
||
// URL'den veya Component Prop'dan gelen parametreleri set et
|
||
if (!searchParams) {
|
||
continue
|
||
}
|
||
|
||
const rawFilter = searchParams?.get('filter')
|
||
if (rawFilter) {
|
||
const parsed = JSON.parse(rawFilter)
|
||
const filters = extractSearchParamsFields(parsed)
|
||
|
||
const hasFilter = filters.some(([field, op, val]) => field === colFormat.fieldName)
|
||
|
||
if (hasFilter) {
|
||
const fieldMatch = filters.find(([field, op, val]) => field === colFormat.fieldName)
|
||
|
||
if (fieldMatch) {
|
||
const [, , val] = fieldMatch
|
||
|
||
const dType = colFormat.dataType as DataType
|
||
|
||
switch (dType) {
|
||
case 'date':
|
||
case 'datetime':
|
||
e.data[colFormat.fieldName] = new Date(val)
|
||
break
|
||
case 'number':
|
||
e.data[colFormat.fieldName] = Number(val)
|
||
break
|
||
case 'boolean':
|
||
e.data[colFormat.fieldName] = val === true || val === 'true'
|
||
break
|
||
case 'object':
|
||
try {
|
||
e.data[colFormat.fieldName] = JSON.parse(val)
|
||
} catch {}
|
||
break
|
||
default:
|
||
e.data[colFormat.fieldName] = val
|
||
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-end',
|
||
},
|
||
)
|
||
}
|
||
|
||
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)
|
||
}
|
||
|
||
if (refListFormCode.current !== listFormCode) {
|
||
setExtraFilters([])
|
||
}
|
||
}, [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)
|
||
}
|
||
}
|
||
|
||
if (gridDto?.gridOptions.extraFilterDto) {
|
||
setExtraFilters(
|
||
gridDto.gridOptions.extraFilterDto.map((f) => ({
|
||
fieldName: f.fieldName,
|
||
operator: f.operator,
|
||
controlType: f.controlType,
|
||
value: f.defaultValue ?? '',
|
||
})),
|
||
)
|
||
}
|
||
}, [gridDto])
|
||
|
||
useEffect(() => {
|
||
if (!gridDto) return
|
||
|
||
const cols = getBandedColumns()
|
||
setColumnData(cols)
|
||
|
||
const dataSource = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams, cols)
|
||
setGridDataSource(dataSource)
|
||
}, [gridDto, searchParams])
|
||
|
||
useEffect(() => {
|
||
const activeFilters = extraFilters.filter((f) => f.value)
|
||
|
||
let base: any = null
|
||
if (defaultSearchParams.current) {
|
||
base = JSON.parse(defaultSearchParams.current)
|
||
}
|
||
|
||
// Default filter tripletlerini çıkar
|
||
const baseTriplets = extractSearchParamsFields(base)
|
||
|
||
// Extra filter tripletleri hazırla
|
||
const extraTriplets = activeFilters.map(
|
||
(f) => [f.fieldName, f.operator, f.value] as [string, string, any],
|
||
)
|
||
|
||
// Tripletleri birleştir, aynı field+op varsa sonuncuyu al
|
||
const merged = [...baseTriplets, ...extraTriplets].reduce(
|
||
(acc, cur) => {
|
||
const [field, op] = cur
|
||
const idx = acc.findIndex((a) => a[0] === field && a[1] === op)
|
||
if (idx >= 0) {
|
||
acc[idx] = cur // varsa üzerine yaz
|
||
} else {
|
||
acc.push(cur)
|
||
}
|
||
return acc
|
||
},
|
||
[] as [string, string, any][],
|
||
)
|
||
|
||
// Tek filtre varsa direkt yaz
|
||
let filter: any = null
|
||
if (merged.length === 1) {
|
||
filter = merged[0]
|
||
} else if (merged.length > 1) {
|
||
filter = merged.reduce((acc, f, idx) => {
|
||
if (idx === 0) return f
|
||
return [acc, 'and', f]
|
||
}, null as any)
|
||
}
|
||
|
||
if (filter) {
|
||
searchParams?.set('filter', JSON.stringify(filter))
|
||
} else {
|
||
searchParams?.delete('filter')
|
||
}
|
||
|
||
gridRef.current?.instance.refresh()
|
||
}, [extraFilters])
|
||
|
||
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 = async (e: DataGridTypes.ExportingEvent) => {
|
||
// DevExtreme’in varsayılan export davranışını iptal ediyoruz; kendi akışımızı çalıştıracağız
|
||
e.cancel = true
|
||
|
||
const grid = gridRef?.current?.instance
|
||
if (!grid) return
|
||
|
||
try {
|
||
if (e.format === 'xlsx' || e.format === 'csv') {
|
||
// exceljs + file-saver + devextreme excel exporter => ihtiyaç anında yükle
|
||
const [{ Workbook }, { saveAs }, { exportDataGrid: exportDataExcel }] = await Promise.all([
|
||
import('exceljs'),
|
||
import('file-saver'),
|
||
import('devextreme/excel_exporter'),
|
||
])
|
||
|
||
const workbook = new Workbook()
|
||
const worksheet = workbook.addWorksheet(`${listFormCode}_sheet`)
|
||
|
||
await exportDataExcel({
|
||
component: grid,
|
||
worksheet,
|
||
autoFilterEnabled: true,
|
||
})
|
||
|
||
if (e.format === 'xlsx') {
|
||
const buffer = await workbook.xlsx.writeBuffer()
|
||
saveAs(
|
||
new Blob([buffer], { type: 'application/octet-stream' }),
|
||
`${listFormCode}_export.xlsx`,
|
||
)
|
||
} else {
|
||
const buffer = await workbook.csv.writeBuffer()
|
||
saveAs(
|
||
new Blob([buffer], { type: 'application/octet-stream' }),
|
||
`${listFormCode}_export.csv`,
|
||
)
|
||
}
|
||
} else if (e.format === 'pdf') {
|
||
// jspdf + devextreme pdf exporter => ihtiyaç anında yükle
|
||
const [jspdfMod, { exportDataGrid: exportDataPdf }] = await Promise.all([
|
||
import('jspdf'),
|
||
import('devextreme/pdf_exporter'),
|
||
])
|
||
|
||
// jsPDF bazı paketlemelerde default, bazılarında named export olarak gelir
|
||
const JsPDFCtor = (jspdfMod as any).default ?? (jspdfMod as any).jsPDF
|
||
const doc = new JsPDFCtor({})
|
||
|
||
await exportDataPdf({
|
||
jsPDFDocument: doc,
|
||
component: grid,
|
||
indent: 5,
|
||
})
|
||
|
||
doc.save(`${listFormCode}_export.pdf`)
|
||
}
|
||
} catch (err) {
|
||
console.error('Export error:', err)
|
||
toast.push(
|
||
<Notification type="danger" duration={2500}>
|
||
{translate('::App.Common.ExportError') ?? 'Dışa aktarma sırasında hata oluştu.'}
|
||
</Notification>,
|
||
{ placement: 'top-end' },
|
||
)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<WidgetGroup widgetGroups={gridDto?.widgets ?? []} />
|
||
|
||
<Container className={DX_CLASSNAMES}>
|
||
{!isSubForm && (
|
||
<Helmet
|
||
titleTemplate="%s | Sözsoft Kurs Platform"
|
||
title={translate('::' + gridDto?.gridOptions.title)}
|
||
defaultTitle="Sözsoft Kurs Platform"
|
||
></Helmet>
|
||
)}
|
||
{gridDto && columnData && (
|
||
<>
|
||
<div className="p-1">
|
||
<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?.()
|
||
}}
|
||
onEditorPreparing={(editor) => {
|
||
if (editor.parentType === 'dataRow' && editor.dataField) {
|
||
const formItem = gridDto.gridOptions.editingFormDto
|
||
.flatMap((group) => group.items || [])
|
||
.find((i) => i.dataField === editor.dataField)
|
||
|
||
if (formItem?.script) {
|
||
const prevHandler = editor.editorOptions.onValueChanged // varsa önceki handler'ı sakla
|
||
|
||
editor.editorOptions.onValueChanged = (e: any) => {
|
||
// yeni handler
|
||
if (prevHandler) prevHandler(e)
|
||
|
||
try {
|
||
const grid = editor.component
|
||
const rowKey = grid.option('editing.editRowKey')
|
||
const rowIndex = grid.getRowIndexByKey(rowKey)
|
||
|
||
// formData → aktif satırın datası
|
||
const formData =
|
||
grid.getVisibleRows().find((r) => r.key === rowKey)?.data || {}
|
||
|
||
// setFormData → komple yeni obje vererek güncelleme
|
||
const setFormData = (newData: any) => {
|
||
if (rowIndex >= 0) {
|
||
Object.keys(newData).forEach((field) => {
|
||
grid.cellValue(rowIndex, field, newData[field])
|
||
})
|
||
}
|
||
}
|
||
|
||
eval(formItem.script!)
|
||
//setFormData({ ...formData, Path: e.value, Authority: e.value })
|
||
|
||
// editor.component.cellValue(
|
||
// editor.component.getRowIndexByKey(
|
||
// editor.component.option('editing.editRowKey'),
|
||
// ),
|
||
// 'Path',
|
||
// e.value,
|
||
// )
|
||
} catch (err) {
|
||
console.error('Script exec error', formItem.dataField, err)
|
||
}
|
||
}
|
||
}
|
||
|
||
// 🔥 Butonların onClick eventlerini wrap et
|
||
if (editor.editorOptions?.buttons) {
|
||
editor.editorOptions.buttons = editor.editorOptions.buttons.map(
|
||
(btn: any) => {
|
||
if (btn?.options?.onClick && typeof btn.options.onClick === 'function') {
|
||
const origClick = btn.options.onClick
|
||
btn.options.onClick = (e: any) => {
|
||
const grid = editor.component
|
||
const rowKey = grid.option('editing.editRowKey')
|
||
const rowIndex = grid.getRowIndexByKey(rowKey)
|
||
const formData =
|
||
grid.getVisibleRows().find((r) => r.key === rowKey)?.data || {}
|
||
|
||
origClick({
|
||
...e,
|
||
formData,
|
||
fieldName: editor.dataField,
|
||
rowKey,
|
||
rowIndex,
|
||
})
|
||
}
|
||
}
|
||
return btn
|
||
},
|
||
)
|
||
}
|
||
}
|
||
}}
|
||
>
|
||
<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={{
|
||
onFieldDataChanged: (e) => {
|
||
if (e.dataField) {
|
||
const formItem = gridDto.gridOptions.editingFormDto
|
||
.flatMap((group) => group.items || [])
|
||
.find((i) => i.dataField === e.dataField)
|
||
if (formItem?.script) {
|
||
try {
|
||
//setFormData({...formData, Path: e.value});
|
||
//UiEvalService.ApiGenerateBackgroundWorkers();
|
||
//setFormData({ ...formData, Path: (v => v === '1' ? '1-deneme' : v === '0' ? '0-deneme' : '')(e.value) })
|
||
eval(formItem.script)
|
||
} catch (err) {
|
||
console.error('Script exec error', err)
|
||
}
|
||
}
|
||
}
|
||
},
|
||
items:
|
||
gridDto.gridOptions.editingFormDto?.length > 0
|
||
? gridDto.gridOptions.editingFormDto
|
||
?.sort((a: any, b: any) => {
|
||
return a.order >= b.order ? 1 : -1
|
||
})
|
||
.map((e: any) => {
|
||
return {
|
||
itemType: e.itemType,
|
||
colCount: e.colCount,
|
||
colSpan: e.colSpan,
|
||
caption: e.caption,
|
||
items: e.items
|
||
?.sort((a: any, b: any) => {
|
||
return a.order >= b.order ? 1 : -1
|
||
})
|
||
.map((i: EditingFormItemDto) => {
|
||
let editorOptions: EditorOptionsWithButtons = {}
|
||
try {
|
||
editorOptions = i.editorOptions && JSON.parse(i.editorOptions)
|
||
|
||
if (editorOptions?.buttons) {
|
||
/*
|
||
{
|
||
"buttons": [
|
||
{
|
||
"name": "custom",
|
||
"location": "after",
|
||
"options": {
|
||
"icon": "plus",
|
||
"onClick": "function(e) { alert('Button clicked for ' + formData[i.dataField]); }"
|
||
}
|
||
}
|
||
]
|
||
}
|
||
*/
|
||
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
|
||
},
|
||
)
|
||
}
|
||
|
||
// Eğer default value varsa, bu editörü readonly yapıyoruz
|
||
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,
|
||
script: i.script,
|
||
}
|
||
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: any) => {
|
||
// 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} />
|
||
<Template name="extraFilters">
|
||
<GridExtraFilterToolbar
|
||
filters={gridDto?.gridOptions.extraFilterDto ?? []}
|
||
extraFilters={extraFilters}
|
||
setExtraFilters={setExtraFilters}
|
||
/>
|
||
</Template>
|
||
<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>
|
||
))}
|
||
{/* burada özel filtre alanını Template ile bağla */}
|
||
{gridDto?.gridOptions.extraFilterDto?.length ? (
|
||
<Item location="before" template="extraFilters" cssClass="no-default" />
|
||
) : null}
|
||
</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: any) => +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: any) => !!x.columnTotalSummaryDto?.summaryType)
|
||
.map((x: any) => (
|
||
<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: any) => !!x.columnGroupSummaryDto?.summaryType)
|
||
.map((x: any) => (
|
||
<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>
|
||
</DataGrid>
|
||
|
||
{gridDto?.gridOptions?.subFormsDto?.length > 0 && (
|
||
<>
|
||
<hr className="my-2" />
|
||
<SubForms gridDto={gridDto!} formData={formData} level={level ?? 0} />
|
||
</>
|
||
)}
|
||
|
||
<Dialog
|
||
width={smaller.md ? '100%' : 1000}
|
||
isOpen={filterData.isImportModalOpen || false}
|
||
onClose={() => filterData.setIsImportModalOpen(false)}
|
||
onRequestClose={() => filterData.setIsImportModalOpen(false)}
|
||
>
|
||
<ImportDashboard gridDto={gridDto} />
|
||
</Dialog>
|
||
</div>
|
||
</>
|
||
)}
|
||
|
||
<Dialog
|
||
isOpen={toolbarModalData?.open || false}
|
||
onClose={() => setToolbarModalData(undefined)}
|
||
onRequestClose={() => setToolbarModalData(undefined)}
|
||
>
|
||
{toolbarModalData?.content}
|
||
</Dialog>
|
||
<GridFilterDialogs gridRef={gridRef} listFormCode={listFormCode} {...filterData} />
|
||
</Container>
|
||
</>
|
||
)
|
||
}
|
||
|
||
export default Grid
|