sozsoft-platform/ui/src/views/form/FormDevExpress.tsx

254 lines
9.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { DX_CLASSNAMES } from '@/constants/app.constant'
import {
Form as FormDx,
FormRef,
GroupItem as GroupItemDx,
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'
import { useLocalization } from '@/utils/hooks/useLocalization'
const FormDevExpress = (props: {
listFormCode: string
isSubForm?: boolean
mode: RowMode
refForm: RefObject<FormRef>
formData: any
formItems: GroupItem[]
setFormData: Dispatch<any>
}) => {
const { listFormCode, isSubForm, mode, refForm, formData, formItems, setFormData } = props
const { translate } = useLocalization()
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 (
<FormDx
ref={refForm}
className={`${DX_CLASSNAMES} ${!isSubForm ? 'px-2' : ''} pb-2`}
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
cssClass="font-semibold"
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>
)}
label={{
text: translate('::' + formItem.colData?.captionName),
className: 'font-semibold',
}}
></SimpleItemDx>
) : formItem.editorType2 === PlatformEditorTypes.dxGridBox ? (
<SimpleItemDx
cssClass="font-semibold"
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>
)}
label={{
text: translate('::' + formItem.colData?.captionName),
className: 'font-semibold',
}}
></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,
}
: {}),
...(formItem.colData?.placeHolder
? { placeholder: translate('::' + formItem.colData.placeHolder) }
: {}),
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
}),
}}
label={{ text: translate('::' + formItem.colData?.captionName) }}
/>
)
})}
</GroupItemDx>
)
})}
</FormDx>
)
}
export default FormDevExpress