237 lines
9.1 KiB
TypeScript
237 lines
9.1 KiB
TypeScript
import { DX_CLASSNAMES } from '@/constants/app.constant'
|
||
import {
|
||
Form as FormDx,
|
||
GroupItem as GroupItemDx,
|
||
Label as LabelDx,
|
||
SimpleItem as SimpleItemDx,
|
||
} from 'devextreme-react/form'
|
||
import { FieldDataChangedEvent, GroupItem } from 'devextreme/ui/form'
|
||
import { Dispatch, RefObject, useEffect, useRef } from 'react'
|
||
import { GridBoxEditorComponent } from './editors/GridBoxEditorComponent'
|
||
import { TagBoxEditorComponent } from './editors/TagBoxEditorComponent'
|
||
import { RowMode, SimpleItemWithColData } from './types'
|
||
import { PlatformEditorTypes } from '@/proxy/form/models'
|
||
|
||
const FormDevExpress = (props: {
|
||
listFormCode: string
|
||
isSubForm?: boolean
|
||
mode: RowMode
|
||
refForm: RefObject<FormDx>
|
||
formData: any
|
||
formItems: GroupItem[]
|
||
setFormData: Dispatch<any>
|
||
}) => {
|
||
const { listFormCode, isSubForm, mode, refForm, formData, formItems, setFormData } = props
|
||
|
||
const formDataRef = useRef(formData)
|
||
const formItemsRef = useRef(formItems)
|
||
|
||
useEffect(() => {
|
||
formDataRef.current = formData
|
||
}, [formData])
|
||
|
||
useEffect(() => {
|
||
formItemsRef.current = formItems
|
||
}, [formItems])
|
||
|
||
// formItems değiştiğinde (özellikle cascading alanlar için) editörlerin dataSource'larını güncelle
|
||
useEffect(() => {
|
||
if (!refForm.current?.instance) return
|
||
|
||
const allItems = formItems.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
|
||
|
||
allItems.forEach((item) => {
|
||
if (item.colData?.lookupDto?.dataSourceType && item.editorOptions?.dataSource) {
|
||
try {
|
||
const editor = refForm.current?.instance.getEditor(item.dataField!)
|
||
if (editor) {
|
||
editor.option('dataSource', item.editorOptions.dataSource)
|
||
}
|
||
} catch (err) {
|
||
// Editor henüz oluşmamış olabilir, sessizce devam et
|
||
console.debug('Editor update skipped for', item.dataField, err)
|
||
}
|
||
}
|
||
})
|
||
}, [formItems])
|
||
|
||
// Cascade fieldlerin disabled durumunu güncelle
|
||
const updateCascadeDisabledStates = () => {
|
||
if (!refForm.current?.instance) return
|
||
|
||
const allItems = formItemsRef.current.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
|
||
|
||
allItems.forEach((item) => {
|
||
const cascadeParentFields = item.colData?.lookupDto?.cascadeParentFields
|
||
if (cascadeParentFields) {
|
||
const parentFields = cascadeParentFields.split(',').map((f: string) => f.trim())
|
||
|
||
try {
|
||
const editor = refForm.current?.instance.getEditor(item.dataField!)
|
||
if (editor && mode !== 'view') {
|
||
// Parent fieldlerden en az biri boşsa disabled olmalı
|
||
const shouldDisable = parentFields.some((parentField: string) => {
|
||
return !formDataRef.current || !formDataRef.current[parentField]
|
||
})
|
||
|
||
editor.option('disabled', shouldDisable)
|
||
}
|
||
} catch (err) {
|
||
console.debug('Cascade disabled update skipped for', item.dataField, err)
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
// formData değiştiğinde cascade disabled durumlarını güncelle
|
||
useEffect(() => {
|
||
updateCascadeDisabledStates()
|
||
}, [formData, mode])
|
||
|
||
return (
|
||
<form className={`${DX_CLASSNAMES} ${!isSubForm ? 'px-2' : ''} pb-2`}>
|
||
<FormDx
|
||
ref={refForm}
|
||
formData={formData}
|
||
onFieldDataChanged={async (e: FieldDataChangedEvent) => {
|
||
const newFormData = { ...formData, [e.dataField!]: e.value }
|
||
|
||
// Cascading child field'leri temizle (parent field değiştiğinde)
|
||
const allItems = formItemsRef.current.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
|
||
const cascadingChildren = allItems.filter((item) => {
|
||
const parentFields = item.colData?.lookupDto?.cascadeParentFields?.split(',') || []
|
||
return parentFields.some(field => field.trim() === e.dataField)
|
||
})
|
||
|
||
// Parent field değiştiğinde child field'leri temizle
|
||
cascadingChildren.forEach((child) => {
|
||
newFormData[child.dataField!] = null
|
||
})
|
||
|
||
setFormData(newFormData)
|
||
|
||
// Cascade disabled durumlarını güncelle (setTimeout ile editor güncellemesinden sonra çalışsın)
|
||
setTimeout(() => {
|
||
updateCascadeDisabledStates()
|
||
}, 0)
|
||
|
||
//Dinamik script
|
||
const changeItem = formItemsRef.current
|
||
.flatMap((group) => (group.items as SimpleItemWithColData[]) || [])
|
||
.find((i: SimpleItemWithColData) => i.dataField === e.dataField)
|
||
|
||
if (changeItem?.editorScript) {
|
||
try {
|
||
//setFormData({...formData, Path: e.value});
|
||
//UiEvalService.ApiGenerateBackgroundWorkers();
|
||
//setFormData({ ...formData, Path: (v => v === '1' ? '1-deneme' : v === '0' ? '0-deneme' : '')(e.value) })
|
||
eval(changeItem.editorScript)
|
||
} catch (err) {
|
||
console.error('Script execution failed for', changeItem.name, err)
|
||
}
|
||
}
|
||
}}
|
||
onContentReady={(e) => {
|
||
const groupItems = e.component.option('items') as any[]
|
||
const firstItem = groupItems?.[0]?.items?.[0]
|
||
|
||
if (firstItem?.dataField) {
|
||
const editor = e.component.getEditor(firstItem.dataField)
|
||
mode !== 'view' && editor?.focus()
|
||
}
|
||
}}
|
||
>
|
||
{formItems.map((formGroupItem, i) => {
|
||
return (
|
||
<GroupItemDx
|
||
key={'formGroupItem-' + i}
|
||
colCount={formGroupItem.colCount}
|
||
colSpan={formGroupItem.colSpan}
|
||
caption={formGroupItem.caption}
|
||
>
|
||
{(formGroupItem.items as SimpleItemWithColData[])?.map((formItem, i) => {
|
||
return formItem.editorType2 === PlatformEditorTypes.dxTagBox ? (
|
||
<SimpleItemDx
|
||
key={'formItem-' + i}
|
||
{...formItem}
|
||
render={() => (
|
||
<TagBoxEditorComponent
|
||
value={formData[formItem.dataField!] || []}
|
||
setDefaultValue={false}
|
||
values={formData}
|
||
options={formItem.tagBoxOptions}
|
||
col={formItem.colData}
|
||
onValueChanged={(e: any) => {
|
||
setFormData({ ...formData, [formItem.dataField!]: e })
|
||
}}
|
||
editorOptions={{
|
||
...formItem.editorOptions,
|
||
...(mode === 'view' ? { readOnly: true } : {}),
|
||
}}
|
||
></TagBoxEditorComponent>
|
||
)}
|
||
>
|
||
<LabelDx text={formItem.name} />
|
||
</SimpleItemDx>
|
||
) : formItem.editorType2 === PlatformEditorTypes.dxGridBox ? (
|
||
<SimpleItemDx
|
||
key={'formItem-' + i}
|
||
{...formItem}
|
||
render={() => (
|
||
<GridBoxEditorComponent
|
||
value={formData[formItem.dataField!] || []}
|
||
values={formData}
|
||
options={formItem.gridBoxOptions}
|
||
col={formItem.colData}
|
||
onValueChanged={(e: any) => {
|
||
setFormData({ ...formData, [formItem.dataField!]: e })
|
||
}}
|
||
editorOptions={{
|
||
...formItem.editorOptions,
|
||
...(mode === 'view' ? { readOnly: true } : {}),
|
||
}}
|
||
></GridBoxEditorComponent>
|
||
)}
|
||
>
|
||
<LabelDx text={formItem.name} />
|
||
</SimpleItemDx>
|
||
) : (
|
||
<SimpleItemDx
|
||
cssClass="font-semibold"
|
||
key={'formItem-' + i}
|
||
{...formItem}
|
||
editorOptions={{
|
||
...formItem.editorOptions,
|
||
...(mode === 'view' ? { readOnly: true } : { autoFocus: i === 1 }),
|
||
...(formItem.editorType === 'dxDateBox' ? {
|
||
useMaskBehavior: true,
|
||
openOnFieldClick: true,
|
||
showClearButton: true,
|
||
} : {}),
|
||
buttons: (formItem.editorOptions?.buttons || []).map((btn: any) => {
|
||
if (btn?.options?.onClick && typeof btn.options.onClick === 'string') {
|
||
const origClick = eval(`(${btn.options.onClick})`)
|
||
btn.options.onClick = (e: any) => {
|
||
origClick({
|
||
...e,
|
||
formData: formDataRef.current,
|
||
fieldName: formItem.dataField,
|
||
mode,
|
||
})
|
||
}
|
||
}
|
||
return btn
|
||
}),
|
||
}}
|
||
/>
|
||
)
|
||
})}
|
||
</GroupItemDx>
|
||
)
|
||
})}
|
||
</FormDx>
|
||
</form>
|
||
)
|
||
}
|
||
|
||
export default FormDevExpress
|