diff --git a/ui/src/views/list/CardView.tsx b/ui/src/views/list/CardView.tsx index 5250bf66..ae953d2e 100644 --- a/ui/src/views/list/CardView.tsx +++ b/ui/src/views/list/CardView.tsx @@ -1,3 +1,12 @@ +// URLSearchParams'ı primitive objeye çeviren yardımcı fonksiyon +function getSearchParamsObject(searchParams?: URLSearchParams) { + if (!searchParams) return undefined; + const obj: Record = {}; + 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>() + 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 */} @@ -1180,7 +1134,11 @@ const CardView = (props: CardViewProps) => { {/* Paging */} - + {/* Pager */}