sozsoft-platform/ui/src/views/list/useListFormColumns.ts

887 lines
29 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 { DataGridTypes } from 'devextreme-react/data-grid'
import { DataType, HorizontalEdge, SortOrder, ValidationRule } from 'devextreme/common'
import CustomStore from 'devextreme/data/custom_store'
import { SelectedFilterOperation } from 'devextreme/ui/data_grid'
import { useCallback, useEffect } from 'react'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { usePermission } from '@/utils/hooks/usePermission'
import { usePWA } from '@/utils/hooks/usePWA'
import { useDialogContext } from '../shared/DialogContext'
import { dynamicFetch } from '@/services/form.service'
import { GridColumnData } from './GridColumnData'
import { useLocation } from 'react-router-dom'
import {
ColumnFormatDto,
EditingFormItemDto,
GridDto,
PlatformEditorTypes,
UiCommandButtonPositionTypeEnum,
UiLookupDataSourceTypeEnum,
} from '@/proxy/form/models'
import { addCss } from './Utils'
const cellTemplateMultiValue = (
cellElement: HTMLElement,
cellInfo: DataGridTypes.ColumnCellTemplateData<any, any>,
) => {
if (cellInfo?.value) {
const values = Array.isArray(cellInfo.value)
? cellInfo.value.map((a: any) => {
const { lookup } = cellInfo.column
if (lookup && lookup.calculateCellValue) {
return lookup.calculateCellValue(a)
}
return ''
})
: [cellInfo.value]
// Badge benzeri HTML üret
const html = values
.filter((v) => v)
.map(
(v) => `
<div
style="
display:inline-block;
background-color:#dc3545;
color:#fff;
border-radius:12px;
padding:2px 8px;
margin:2px 2px;
font-size:12px;
font-weight:300;
line-height:1.4;
white-space:nowrap;
"
>
${v}
</div>
`,
)
.join('')
cellElement.innerHTML = html
cellElement.title = values.join(',')
}
}
// Hover preview overlay — singleton, tüm grid hücreleri tarafından paylaşılır
let __imgPreviewEl: HTMLDivElement | null = null
function getImgPreview(): HTMLDivElement {
if (!__imgPreviewEl) {
const el = document.createElement('div')
el.id = '__cellImgPreview'
el.style.cssText = [
'position:fixed',
'z-index:99999',
'display:none',
'pointer-events:none',
'background:#fff',
'border:1px solid #d1d5db',
'border-radius:8px',
'box-shadow:0 8px 32px rgba(0,0,0,0.22)',
'padding:4px',
'max-width:320px',
'max-height:320px',
'overflow:hidden',
'transition:opacity 0.15s ease',
'opacity:0',
].join(';')
const img = document.createElement('img')
img.style.cssText =
'display:block;max-width:312px;max-height:312px;object-fit:contain;border-radius:4px;'
el.appendChild(img)
document.body.appendChild(el)
__imgPreviewEl = el
}
return __imgPreviewEl
}
function showImgPreview(src: string, e: MouseEvent) {
const el = getImgPreview()
const imgEl = el.querySelector('img') as HTMLImageElement
if (imgEl.src !== src) imgEl.src = src
const GAP = 12
const vw = window.innerWidth
const vh = window.innerHeight
el.style.opacity = '0'
el.style.display = 'block'
const pw = el.offsetWidth || 320
const ph = el.offsetHeight || 320
let left = e.clientX + GAP
let top = e.clientY + GAP
if (left + pw > vw - 8) left = e.clientX - pw - GAP
if (top + ph > vh - 8) top = e.clientY - ph - GAP
if (left < 8) left = 8
if (top < 8) top = 8
el.style.left = `${left}px`
el.style.top = `${top}px`
el.style.opacity = '1'
}
function hideImgPreview() {
if (__imgPreviewEl) {
__imgPreviewEl.style.opacity = '0'
__imgPreviewEl.style.display = 'none'
}
}
const cellTemplateImage = (
cellElement: HTMLElement,
cellInfo: DataGridTypes.ColumnCellTemplateData<any, any>,
) => {
if (cellInfo?.value) {
const urls: string[] = Array.isArray(cellInfo.value)
? cellInfo.value.filter(Boolean)
: [cellInfo.value].filter(Boolean)
//const col = cellInfo.column as any
//const imgOptions = col?.extras?.imageUploadOptions ?? {}
//const w: number = imgOptions.width ?? 40
//const h: number = imgOptions.height ?? 40
const w: number = 40
const h: number = 40
cellElement.style.cssText += 'display:flex;flex-wrap:wrap;align-items:center;gap:4px;'
cellElement.innerHTML = ''
//cellElement.title = urls.join(', ')
urls.forEach((url) => {
const img = document.createElement('img')
img.src = url
img.alt = ''
img.style.cssText = `width:${w}px;height:${h}px;object-fit:cover;border-radius:4px;border:1px solid #ddd;margin:2px;vertical-align:middle;display:inline-block;cursor:zoom-in;`
img.addEventListener('mouseenter', (e) => showImgPreview(url, e as MouseEvent))
img.addEventListener('mousemove', (e) => showImgPreview(url, e as MouseEvent))
img.addEventListener('mouseleave', hideImgPreview)
cellElement.appendChild(img)
})
}
}
function calculateFilterExpressionMultiValue(
this: DataGridTypes.Column,
filterValue: any,
selectedFilterOperation: string | null,
): string | Array<any> {
if (filterValue) {
if (selectedFilterOperation == '=' || selectedFilterOperation === null) {
return [this.dataField, 'contains', filterValue]
} else if (selectedFilterOperation == '<>') {
return [this.dataField, 'notcontains', filterValue]
} else {
return [this.dataField, selectedFilterOperation, filterValue]
}
} else {
// filterValue null ise isblank veya isnotblank secilmistir
if (selectedFilterOperation === '=') {
return [
this.dataField,
selectedFilterOperation,
filterValue,
'or',
this.dataField,
selectedFilterOperation,
' ',
]
} else if (selectedFilterOperation === '<>') {
return [
this.dataField,
selectedFilterOperation,
filterValue,
'and',
this.dataField,
selectedFilterOperation,
' ',
]
} else {
return [this.dataField, selectedFilterOperation, filterValue]
}
}
}
// lookup cache (module scope) - cache süresini ve boyutunu yönet
const __lookupCache = new Map<string, { promise: Promise<any[]>; timestamp: number }>()
const CACHE_DURATION = 5 * 60 * 1000 // 5 dakika
const MAX_CACHE_SIZE = 100 // Maksimum cache entry sayısı
const cachedLoader = (key: string, loader: () => Promise<any[]>) => {
const now = Date.now()
const cached = __lookupCache.get(key)
// Cache'de var ve süresi dolmamışsa kullan
if (cached && now - cached.timestamp < CACHE_DURATION) {
return cached.promise
}
// Cache boyutu limitini aşarsa en eskiyi temizle
if (__lookupCache.size >= MAX_CACHE_SIZE) {
const oldestKey = Array.from(__lookupCache.entries()).sort(
(a, b) => a[1].timestamp - b[1].timestamp,
)[0][0]
__lookupCache.delete(oldestKey)
}
const p = Promise.resolve()
.then(() => loader())
.then((res) => res ?? [])
.catch((err) => {
__lookupCache.delete(key) // hata olursa tekrar denenebilsin
throw err
})
__lookupCache.set(key, { promise: p, timestamp: now })
return p
}
const useListFormColumns = ({
gridDto,
listFormCode,
isSubForm,
gridRef,
}: {
gridDto?: GridDto
listFormCode: string
isSubForm?: boolean
gridRef?: any
}) => {
const dialog: any = useDialogContext()
const { translate } = useLocalization()
const { checkPermission } = usePermission()
const isPwaMode = usePWA()
const location = useLocation()
useEffect(() => {
// listFormCode değişince lookup cache temizlensin (farklı form farklı lookuplar)
__lookupCache.clear()
}, [listFormCode])
const lookupDataSource = useCallback(
(options: any, colData: any, listFormCode: string) => {
const { lookupDto } = colData
const filters = []
if (lookupDto.cascadeParentFields) {
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
filters.push([
lookupDto?.cascadeRelationField,
lookupDto?.cascadeFilterOperator,
options?.data[lookupDto?.cascadeParentField],
])
//TODO: Statik data test edilecek
} else {
const data = options?.data ?? options
for (const cascadeParentField of lookupDto.cascadeParentFields.split(',')) {
filters.push(data[cascadeParentField])
}
}
}
//UiLookupDataSourceTypeEnum :
// Data = 1 (Statik Data),
// Query = 2 (API'den geliyor fakat API query çalıştırıyor)
// WebService = 3 (API servisten geliyor)
if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.StaticData) {
return createLookupStaticDataSource(
() => JSON.parse(lookupDto?.lookupQuery),
filters.length ? filters : null,
`static:${listFormCode}:${colData.fieldName}`, // cache key
)
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.Query) {
return createLookupQueryDataSource(listFormCode, colData.fieldName, filters)
} else if (lookupDto.dataSourceType == UiLookupDataSourceTypeEnum.WebService) {
return createLookupApiDataSource(
listFormCode,
lookupDto?.lookupQuery,
filters,
colData.lookupDto?.valueExpr?.toLowerCase(),
)
} else {
return {
store: [],
}
}
},
[listFormCode],
)
const createLookupStaticDataSource = (
load: () => any,
filter: any = null,
key: any = 'static',
sort: any = 'name',
) => ({
store: new CustomStore({
key,
loadMode: 'raw',
load: async (loadOptions) => {
// load fonksiyonu sync sonuç döndürüyor olabilir, o yüzden Promise.resolve ile sar
return cachedLoader(`static:${key}`, () => Promise.resolve(load()))
},
}),
sort,
filter,
})
const createLookupQueryDataSource = (
listFormCode?: string,
listFormFieldName?: string,
filters?: any[],
) => {
return new CustomStore({
loadMode: 'raw',
load: async (loadOptions) => {
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
return
}
try {
const cacheKey = `query:${listFormCode}:${listFormFieldName}:${JSON.stringify(filters ?? null)}`
return cachedLoader(cacheKey, async () => {
const response = await dynamicFetch('list-form-select/lookup', 'POST', null, {
listFormCode,
listFormFieldName,
filters,
})
return (response.data ?? []).map((a: any) => ({
key: a.Key,
name: a.Name,
group: a.Group,
...a,
}))
})
} catch (error: any) {
return null
}
},
})
}
const createLookupApiDataSource = (
listFormCode?: string,
lookupQuery?: string,
filters?: any[],
keyName?: string,
) => {
return new CustomStore({
key: keyName,
loadMode: 'raw',
load: async (loadOptions) => {
if (!isSubForm && listFormCode && !window.location.pathname.includes(listFormCode)) {
return
}
if (!lookupQuery) {
return
}
const [method, url, body, keySelector, nameSelector, groupSelector] = lookupQuery.split(';')
// body içindeki @paramN'leri filtrelerle değiştir
let resolvedBody = body
if (filters?.length) {
for (let i = 0; i < filters.length; i++) {
resolvedBody = resolvedBody.replace(new RegExp(`@param${i}`, 'g'), filters[i])
}
}
try {
const cacheKey = `api:${lookupQuery}:${JSON.stringify(filters ?? null)}`
return cachedLoader(cacheKey, async () => {
const response = await dynamicFetch(url, method, null, resolvedBody)
let { data } = response
if (!data) return []
if (!Array.isArray(data)) data = [data]
return data.map((a: any) => ({
key: eval(keySelector),
name: eval(nameSelector),
group: eval(groupSelector),
...a,
}))
})
} catch {
return
}
},
})
}
const getCommandColumn = useCallback((): GridColumnData | undefined => {
if (!gridDto) {
return
}
const hasCreate =
gridDto.gridOptions.editingOptionDto.allowAdding &&
checkPermission(gridDto.gridOptions.permissionDto.i)
const hasUpdate =
gridDto.gridOptions.editingOptionDto.allowUpdating &&
checkPermission(gridDto.gridOptions.permissionDto.u)
const hasDelete =
gridDto.gridOptions.editingOptionDto.allowDeleting &&
checkPermission(gridDto.gridOptions.permissionDto.d)
const hasDetail =
gridDto.gridOptions.editingOptionDto.allowDetail &&
checkPermission(gridDto.gridOptions.permissionDto.u)
const hasDuplicate =
gridDto.gridOptions.editingOptionDto.allowDuplicate &&
checkPermission(gridDto.gridOptions.permissionDto.i)
const hasCommandButtons = gridDto.gridOptions.commandColumnDto.length > 0
// Eğer hiçbir buton eklenecek durumda değilse: çık
if (!hasUpdate && !hasDelete && !hasCreate && !hasCommandButtons) {
return
}
const buttons: any[] = []
if (hasUpdate) {
buttons.push({
name: 'edit',
text: translate('::App.Platform.Edit'),
})
}
if (hasDelete) {
buttons.push({
name: 'delete',
text: translate('::App.Platform.Delete'),
})
}
if (hasDetail) {
const item = {
name: 'detail',
text: translate('::App.Platform.Detail'),
onClick: (e: any) => {
if (typeof e.event?.preventDefault === 'function') {
e.event.preventDefault()
}
if (!gridDto.gridOptions.keyFieldName) return
const detailFormName = gridDto.gridOptions.listFormCode
const id = e.row.data[gridDto.gridOptions.keyFieldName]
const url = `/admin/form/${detailFormName}/${id}`
window.open(url, isPwaMode ? '_self' : '_blank')
},
}
buttons.push(item)
}
if (hasDuplicate) {
const item = {
name: 'duplicate',
text: translate('::App.Platform.Duplicate'),
onClick: async (e: any) => {
if (typeof e.event?.preventDefault === 'function') {
e.event.preventDefault()
}
// Onay penceresi
const confirmed = window.confirm(
translate('::App.Platform.DuplicateConfirm') || 'Kopyalama işlemini onaylıyor musunuz?',
)
if (!confirmed) return
if (!gridDto.gridOptions.keyFieldName) return
const id = e.row.data[gridDto.gridOptions.keyFieldName]
if (!id) return
// Backend'e duplicate isteği gönder
try {
await dynamicFetch('list-form-data/duplicate', 'POST', null, {
listFormCode,
keys: [id],
data: [gridDto.gridOptions.keyFieldName],
})
// Başarılı ise grid'i yenile
if (gridRef?.current?.instance()) {
gridRef.current.instance().refresh()
}
} catch (err) {
// Hata yönetimi
alert(translate('::App.Platform.DuplicateError'))
}
},
}
buttons.push(item)
}
gridDto.gridOptions.commandColumnDto.forEach((action) => {
if (action.buttonPosition !== UiCommandButtonPositionTypeEnum.CommandColumn) return
if (!checkPermission(action.authName)) return
// visibleExpression varsa dinamik fonksiyon oluştur, yoksa statik değer kullan
let visibleFunc: ((e: any) => boolean) | boolean = action.isVisible
if (action.visibleExpression) {
try {
// visibleExpression string'ini fonksiyona çevir
// Örnek: "(e) => !e.row.isEditing" veya "(e) => e.row.data.Status === 'Active'"
visibleFunc = eval(action.visibleExpression)
} catch (error) {
console.error('VisibleExpression evaluation error:', error, action.visibleExpression)
visibleFunc = action.isVisible // Hata durumunda varsayılan değeri kullan
}
}
const item = {
visible: visibleFunc,
icon: action.icon,
hint: translate('::' + action.hint),
text: translate('::' + action.text),
onClick: (e: any) => {
if (typeof e.event?.preventDefault === 'function') {
e.event.preventDefault()
}
if (action.url) {
let url = action.url?.replace('@LISTFORMCODE', listFormCode)
gridDto.columnFormats.forEach((field) => {
if (field.fieldName) {
url = url.replace(`@${field.fieldName}`, e.row.data[field.fieldName])
}
})
window.open(url, isPwaMode ? '_self' : action.urlTarget)
} else if (action.dialogName) {
if (action.dialogParameters) {
const dynamicMap = JSON.parse(action.dialogParameters)
for (const [key, value] of Object.entries<string>(dynamicMap)) {
dynamicMap[key] = value.startsWith('@') ? e.row.data[value.replace('@', '')] : value
}
dialog.setConfig({
component: action.dialogName,
props: dynamicMap,
onClose: () => {
// Dialog kapandığında grid'i yenile
if (gridRef?.current?.instance()) {
gridRef?.current?.instance().refresh()
}
},
})
}
} else if (action.onClick) {
eval(action.onClick)
}
},
}
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 + 50, 200)
const column = {
type: 'buttons',
width: calculatedWidth,
minWidth: calculatedWidth,
buttons,
allowResizing: true,
}
return column as GridColumnData
}, [gridDto, checkPermission, translate, listFormCode, isPwaMode, dialog, gridRef])
const getColumns = useCallback(
(columnFormats: ColumnFormatDto[]) => {
const columns: GridColumnData[] = []
if (!gridDto || !columnFormats) {
return columns
}
columnFormats.forEach((colData) => {
if (!colData.canRead || !colData.isActive) {
return
}
const column: GridColumnData = {}
column.colData = colData // Onemli: Baska event-callback lerde kullanmak icin eklendi, colData.lookupDto?.editorTemplateType
//column.showEditorAlways = true
column.dataField = colData.fieldName
if (colData.dataType) column.dataType = colData.dataType as DataType
if (colData.captionName) column.caption = translate('::' + colData.captionName)
if (colData.width > 0) column.width = colData.width
column.visible = colData.visible
column.alignment = colData.alignment
column.format = colData.format
let editorOptions: any = {}
if (colData.editorOptions) {
try {
editorOptions =
typeof colData.editorOptions === 'string'
? JSON.parse(colData.editorOptions)
: colData.editorOptions
} catch {
editorOptions = {}
}
}
column.editorOptions = { ...editorOptions }
// Format bilgisini öncelik sırasına göre ata
if (column.editorOptions.displayFormat) {
column.format = column.editorOptions.displayFormat
} else if (column.editorOptions.format) {
column.format = column.editorOptions.format
}
// columnCustomizationDto
column.fixed = colData.columnCustomizationDto?.fixed
column.fixedPosition = colData.columnCustomizationDto?.fixedPosition as HorizontalEdge
column.allowReordering = colData.columnCustomizationDto?.allowReordering
// sort
if (colData.sortIndex >= 0) {
column.sortIndex = colData.sortIndex
column.sortOrder = colData.sortDirection as SortOrder
}
// filterRow
column.allowFiltering = colData.columnFilterDto?.allowFiltering
column.selectedFilterOperation = colData.columnFilterDto
?.selectedFilterOperation as SelectedFilterOperation
column.filterValue = colData.columnFilterDto?.filterValue
// headerFilter
column.allowHeaderFiltering = colData.columnHeaderDto?.allowHeaderFiltering
if (column.allowHeaderFiltering == true) {
column.headerFilter = {}
column.headerFilter.allowSearch = colData.columnHeaderDto?.allowSearch
column.headerFilter.dataSource = colData.columnHeaderDto?.dataSource
}
// search
column.allowSearch = colData.allowSearch
//export
column.allowExporting = colData.canExport
// grouping
column.allowGrouping = colData.columnGroupingDto?.allowGrouping
column.autoExpandGroup = colData.columnGroupingDto?.autoExpandGroup
if (colData.columnGroupingDto.groupIndex)
column.groupIndex = colData.columnGroupingDto?.groupIndex
// constsa dinamik olarak css verilerini ekle
if (colData.columnCssClass) {
column.cssClass = colData.columnCssClass
if (colData.columnCssValue) {
addCss(colData.columnCssValue)
}
}
column.allowEditing = colData?.allowEditing || colData?.allowAdding
// #region lookup ayarlari
if (colData.lookupDto?.dataSourceType) {
// UiColumnEditorTemplateTypeEnum : None:0, Table:1, TagBox:2
const allItems = gridDto.gridOptions.editingFormDto.flatMap((group) => group.items)
const formItem = allItems.find((a) => a?.dataField === colData.fieldName)
if (formItem?.editorType2 === PlatformEditorTypes.dxTagBox) {
column.extras = {
multiValue: true,
editorOptions: formItem.editorOptions,
tagBoxOptions: formItem.tagBoxOptions,
}
column.editCellTemplate = 'cellEditTagBox'
column.calculateFilterExpression = calculateFilterExpressionMultiValue
column.cellTemplate = cellTemplateMultiValue
} else if (formItem?.editorType2 === PlatformEditorTypes.dxGridBox) {
column.extras = {
multiValue: false,
editorOptions: formItem.editorOptions,
gridBoxOptions: formItem.gridBoxOptions,
}
column.editCellTemplate = 'cellEditGridBox'
column.cellTemplate = cellTemplateMultiValue
if (formItem.gridBoxOptions?.selectionMode === 'multiple') {
column.calculateFilterExpression = calculateFilterExpressionMultiValue
column.extras.multiValue = true
}
}
column.lookup = {
valueExpr: colData.lookupDto?.valueExpr?.toLowerCase(),
displayExpr: colData.lookupDto?.displayExpr?.toLowerCase(),
dataSource: (o) => lookupDataSource(o, colData, listFormCode),
}
//column.lookup.dataSource = lookupDataSource(null, colData)
//cascadeEmptyFields verisi dolu ise bu kolon/field bir parent field dir
if (colData.lookupDto.cascadeEmptyFields) {
// parent field guncellendigi zaman bu fonksiyon cagrilir
column.setCellValue = function (rowData: any, value: any) {
if (!colData.fieldName) return
//console.log({ rowData, value, colData })
rowData[colData.fieldName] = Array.isArray(value) ? value[0] : value
// cascadeEmptyFields alani aralarinda virgul olacak sekilde bosaltilmak istenen alanlari saklar
colData?.lookupDto?.cascadeEmptyFields?.split(',').forEach((emptyField: any) => {
rowData[emptyField] = null
})
}
}
}
// #endregion
// #region image upload editor
if (!colData.lookupDto?.dataSourceType) {
const allFormItems = gridDto.gridOptions.editingFormDto.flatMap((group) => group.items)
const imageFormItem = allFormItems.find((a) => a?.dataField === colData.fieldName)
if (imageFormItem?.editorType2 === PlatformEditorTypes.dxImageUpload) {
// imageUploadOptions'ı önce imageFormItem.imageUploadOptions'dan al,
// yoksa editorOptions JSON içinden parse et (admin panelinde editorOptions ile yapılandırılır)
let imageUploadOptions = imageFormItem.imageUploadOptions
if (!imageUploadOptions && imageFormItem.editorOptions) {
try {
imageUploadOptions = JSON.parse(imageFormItem.editorOptions)
} catch {
imageUploadOptions = undefined
}
}
// Kolon editorOptions'ından da dene (column-level config)
if (!imageUploadOptions && colData.editorOptions) {
try {
imageUploadOptions =
typeof colData.editorOptions === 'string'
? JSON.parse(colData.editorOptions)
: (colData.editorOptions as any)
} catch {
imageUploadOptions = undefined
}
}
column.extras = {
multiValue: imageUploadOptions?.multiple ?? false,
editorOptions: imageFormItem.editorOptions,
imageUploadOptions: imageUploadOptions,
}
column.editCellTemplate = 'cellEditImageUpload'
column.cellTemplate = cellTemplateImage as any
}
}
// #endregion image upload editor
if (colData.validationRuleDto) {
// for server side validation : https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/DataValidation/jQuery/Light/
column.validationRules = colData.validationRuleDto as ValidationRule[]
}
columns.push(column)
})
return columns
},
[gridDto, lookupDataSource, translate, checkPermission, dialog, isPwaMode, listFormCode],
)
const getBandedColumns = useCallback(() => {
if (!gridDto) {
return
}
const columns: GridColumnData[] = []
const insertedColumns: (string | undefined)[] = []
const commandColumn = getCommandColumn()
if (commandColumn) {
columns.push(commandColumn)
}
for (const col of gridDto.columnFormats) {
if (!col.fieldName) {
return
}
if (insertedColumns.some((a) => a === col.fieldName)) {
// kolon zaten eklenmis ise islem yapma
return
}
if (col.bandName) {
// banded kolon ise; en fazla iki kirilima kadar eklenir
const bands = col.bandName.split(':') // ic ice banded kolon const ise aralarinda : kullanilir
if (bands.length > 1) {
// band + band + column seklinde ise :
let topBand = columns.find((e) => e.caption == bands[0] && e.isBand == true)
if (!topBand) {
// en ustteki band ilk defa ekleniyor ise
topBand = { caption: bands[0], columns: [] as GridColumnData[], isBand: true }
columns.push(topBand)
}
topBand.columns ??= [] as GridColumnData[]
const band2 = { caption: bands[1], columns: [] as GridColumnData[], isBand: true }
topBand.columns.push(band2)
const rData = gridDto.columnFormats.filter((e) => e.bandName == col.bandName)
const cols = getColumns(rData) as GridColumnData[]
band2.columns.push(...cols)
insertedColumns.push(...cols.map((e) => e.dataField))
} else {
// band + column
const band = { caption: bands[0], columns: [] as GridColumnData[], isBand: true }
const rData = gridDto.columnFormats.filter((e) => e.bandName == bands[0])
const cols = getColumns(rData) as GridColumnData[]
band.columns.push(...cols)
columns.push(band)
insertedColumns.push(...cols.map((e) => e.dataField))
}
} else {
// band a bagli olmayan kolonlar
const cols = getColumns([col])
//console.log({ col, cols: JSON.stringify(cols) })
columns.push(...cols)
insertedColumns.push(...cols.map((e) => e.dataField))
}
}
// FormEditingExtraItem
// Devexpress Gridde kaydete basılınca
// formda gözükecek olan EditingFormDto.Items elemanları gelmiyor
// Sadece grid'de tanımlanmış columnları getiriyor.
// Bu elemanları da getirmesi için aşağıdaki şekilde,
// columns'da olmayan alanları da gizli olarak ekliyoruz
if (columns?.length) {
gridDto.gridOptions.editingFormDto.forEach((group) => {
group.items?.forEach((item: EditingFormItemDto) => {
if (!columns.some((a) => a.dataField === item.dataField)) {
columns.push({
dataField: item.dataField,
visible: false,
showInColumnChooser: false,
})
insertedColumns.push(item.dataField)
}
})
})
}
return columns
}, [gridDto, getColumns, getCommandColumn])
return {
getBandedColumns,
}
}
export { useListFormColumns }