CardView düzenlemesi

This commit is contained in:
Sedat ÖZTÜRK 2026-01-27 17:45:56 +03:00
parent 330c1aed19
commit 45a89bd41a

View file

@ -1,3 +1,12 @@
// URLSearchParams'ı primitive objeye çeviren yardımcı fonksiyon
function getSearchParamsObject(searchParams?: URLSearchParams) {
if (!searchParams) return undefined;
const obj: Record<string, string> = {};
for (const [key, value] of searchParams.entries()) {
obj[key] = value;
}
return obj;
}
import Container from '@/components/shared/Container'
import { Notification, toast } from '@/components/ui'
import { DX_CLASSNAMES } from '@/constants/app.constant'
@ -395,13 +404,6 @@ const CardView = (props: CardViewProps) => {
}, [listFormCode])
useEffect(() => {
if (cardViewRef?.current) {
const instance = cardViewRef?.current?.instance()
if (instance) {
instance.option('dataSource', undefined)
}
}
if (refListFormCode.current !== listFormCode) {
setColumnData(undefined)
}
@ -631,104 +633,27 @@ const CardView = (props: CardViewProps) => {
loadLookups()
}, [columnsWithLookup])
// DataSource oluştur - sadece gridDto ve listFormCode değiştiğinde (useMemo ile cache'le)
const cardViewDataSource = useMemo(() => {
if (!gridDto) return null
// Kolonları oluştur - Grid ile aynı şekilde columnData state ile yönet
useEffect(() => {
if (!gridDto || !config) return
const cols = getBandedColumns()
if (!cols || cols.length === 0) return null
setColumnData(cols)
}, [gridDto, config])
const baseStore = createSelectDataSource(
// DataSource'u columnData'ya göre oluştur
const [cardViewDataSource, setCardViewDataSource] = useState<CustomStore<any, any>>()
useEffect(() => {
if (!gridDto || !columnData) return
const ds = createSelectDataSource(
gridDto.gridOptions,
listFormCode,
searchParams,
layoutTypes.cardView,
cols,
columnData
)
// CardView için sadece 1 select çağrısı yapacak wrapper
let cachedData: any[] | null = null
let cachedTotalCount: number = 0
let isLoading = false
const keyExpr = gridDto.gridOptions.keyFieldName
const clearCache = () => {
cachedData = null
cachedTotalCount = 0
isLoading = false
}
// Cache temizleme fonksiyonunu dışarıya expose et
;(window as any).__clearCardViewCache = clearCache
const optimizedStore: any = new CustomStore({
key: keyExpr,
load: async (loadOptions: any) => {
// Zaten yüklenmişse cache'den dön
if (cachedData !== null && !isLoading) {
return {
data: cachedData,
totalCount: cachedTotalCount,
}
}
// Yükleme devam ediyorsa bekle
if (isLoading) {
await new Promise((resolve) => setTimeout(resolve, 100))
if (cachedData !== null) {
return {
data: cachedData,
totalCount: cachedTotalCount,
}
}
}
isLoading = true
try {
const result = await baseStore.load(loadOptions)
cachedData = result?.data || []
cachedTotalCount = result?.totalCount || 0
return result
} finally {
isLoading = false
}
},
byKey: async (key: any) => {
// Cache'de ara
if (cachedData && keyExpr) {
const item = cachedData.find((row: any) => row?.[keyExpr] === key)
if (item) return item
}
// Bulamazsa server'a git
return baseStore.byKey(key)
},
insert: async (values: any) => {
const result = await baseStore.insert(values)
clearCache()
return result
},
update: async (key: any, values: any) => {
const result = await baseStore.update(key, values)
clearCache()
return result
},
remove: async (key: any) => {
const result = await baseStore.remove(key)
clearCache()
return result
},
})
// DataSource içine sar
return new DataSource({
store: optimizedStore,
reshapeOnPush: true,
paginate: true,
pageSize: pageSize,
})
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [gridDto, listFormCode])
setCardViewDataSource(ds)
}, [gridDto, listFormCode, searchParams, columnData])
// extraFilters değişikliğini izlemek için ref
const extraFiltersInitialized = useRef(false)
@ -860,7 +785,6 @@ const CardView = (props: CardViewProps) => {
const extCol = col as any
const colData = gridDto?.columnFormats.find((c) => c.fieldName === col.dataField)
// Column props
const columnProps: any = {
dataField: col.dataField,
caption: col.caption ? translate('::' + col.caption) : captionize(col.dataField || ''),
@ -924,26 +848,60 @@ const CardView = (props: CardViewProps) => {
const onCardsPerRowChanged = useCallback(
(value: number) => {
setCardsPerRow(value)
// localStorage'a kaydet
const storageKey = `cardview-cardsPerRow-${listFormCode}`
localStorage.setItem(storageKey, value.toString())
},
[listFormCode],
[],
)
// Page size değiştiğinde
const onPageSizeChanged = useCallback((newPageSize: number) => {
setPageSize(newPageSize)
const instance = cardViewRef.current?.instance()
if (instance) {
instance.pageSize(newPageSize)
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) {
const extras = gridDto.gridOptions.extraFilterDto.map((f) => ({
fieldName: f.fieldName,
caption: f.caption,
operator: f.operator || '=',
value: f.defaultValue || '',
controlType: f.controlType,
}))
// Sadece ilk yüklemede extraFilters'ı set et, her gridDto değişiminde değil
setExtraFilters((prev) => {
if (prev.length === 0) return extras
return prev
})
}
if (gridDto?.gridOptions.editingOptionDto?.popup) {
setIsPopupFullScreen(gridDto.gridOptions.editingOptionDto.popup.fullScreen)
}
// cardsPerRow başlangıç değeri sadece gridDto'dan alınır
if (gridDto?.gridOptions.layoutDto?.cardLayoutColumn) {
setCardsPerRow(gridDto.gridOptions.layoutDto.cardLayoutColumn)
}
// pageSize başlangıç değeri sadece gridDto'dan alınır
if (gridDto?.gridOptions.pageSize) {
setPageSize(gridDto.gridOptions.pageSize)
}
}, [gridDto, listFormCode])
// Toolbar items
const toolbarItems = useMemo(() => {
if (!gridDto) return []
const items: any[] = [
{ name: 'addCardButton' },
{ name: 'searchPanel' },
@ -1032,8 +990,8 @@ const CardView = (props: CardViewProps) => {
const pagerConfig = useMemo(() => {
const allowedSizes = gridDto?.gridOptions.pagerOptionDto?.allowedPageSizes
?.split(',')
.map((s) => Number(s.trim()))
.filter((n) => !isNaN(n) && n > 0) || [10, 20, 50, 100]
.map((s: string) => Number(s.trim()))
.filter((n: number) => !isNaN(n) && n > 0) || [10, 20, 50, 100]
return {
visible: gridDto?.gridOptions.pagerOptionDto?.visible !== false,
@ -1099,7 +1057,7 @@ const CardView = (props: CardViewProps) => {
? `calc(100vh - ${170 + widgetGroupHeight}px)`
: undefined
}
remoteOperations={false}
remoteOperations={true}
onSelectionChanged={onSelectionChanged as any}
onInitNewCard={onInitNewCard as any}
onCardInserting={onCardInserting as any}
@ -1135,11 +1093,7 @@ const CardView = (props: CardViewProps) => {
props.refreshData?.()
}, 100)
}}
onOptionChanged={(e: any) => {
if (e.name === 'paging.pageSize' && e.value !== pageSize) {
setPageSize(e.value)
}
}}
// onOptionChanged kaldırıldı, pageSize sadece state ve useEffect ile kontrol ediliyor
>
{/* Toolbar */}
<Toolbar items={toolbarItems} />
@ -1180,7 +1134,11 @@ const CardView = (props: CardViewProps) => {
<ColumnChooser enabled={true} mode="select" />
{/* Paging */}
<Paging enabled={pagingConfig.enabled} defaultPageSize={pagingConfig.pageSize} />
<Paging
enabled={pagingConfig.enabled}
pageSize={pageSize}
onPageSizeChange={setPageSize}
/>
{/* Pager */}
<Pager