From 5dd6e0bcd4af9ab8f747282d9d2fbb04767e5c25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96ZT=C3=9CRK?= <76204082+iamsedatozturk@users.noreply.github.com> Date: Mon, 22 Sep 2025 12:11:15 +0300 Subject: [PATCH] =?UTF-8?q?Grid=20=C3=BCzerinde=20Widgets=20=C3=A7al=C4=B1?= =?UTF-8?q?=C5=9Fma=20=C5=9Fekli=20de=C4=9Fi=C5=9Ftirildi.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ListForms/Select/GridDto.cs | 2 + .../ListForms/Select/SelectDto.cs | 2 - .../ListForms/ListFormSelectAppService.cs | 18 +- ui/Kurs.Platform.Ui.Dockerfile | 2 +- ui/public/version.json | 16 +- ui/src/proxy/form/models.ts | 1 + ui/src/shared/useListFormCustomDataSource.ts | 3 - ui/src/views/form/FormButtons.tsx | 2 - ui/src/views/form/FormDevExpress.tsx | 1 - ui/src/views/list/Card.tsx | 188 +++++++++++------- ui/src/views/list/Grid.tsx | 80 ++++---- ui/src/views/list/useToolbar.tsx | 4 - 12 files changed, 194 insertions(+), 125 deletions(-) diff --git a/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/GridDto.cs b/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/GridDto.cs index 7321b206..91f91168 100644 --- a/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/GridDto.cs +++ b/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/GridDto.cs @@ -8,8 +8,10 @@ public class GridDto { ColumnFormats = new List(); GridOptions = new GridOptionsDto(); + Widgets = new List(); } public List ColumnFormats { get; set; } public GridOptionsDto GridOptions { get; set; } + public List Widgets { get; set; } } diff --git a/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/SelectDto.cs b/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/SelectDto.cs index 6d622b9a..05caf9fb 100644 --- a/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/SelectDto.cs +++ b/api/src/Kurs.Platform.Application.Contracts/ListForms/Select/SelectDto.cs @@ -22,6 +22,4 @@ public class SelectDto /// Sonuc ile ilgili bazi bilgileride gonderir. Ornegin: filtre uygulandı mı? Sunucu filtresi uygulandı mı? /// public QueryInfoDto QueryInfos { get; set; } - - public List Widgets { get; set; } } diff --git a/api/src/Kurs.Platform.Application/ListForms/ListFormSelectAppService.cs b/api/src/Kurs.Platform.Application/ListForms/ListFormSelectAppService.cs index c243bdd6..83d4e4a9 100644 --- a/api/src/Kurs.Platform.Application/ListForms/ListFormSelectAppService.cs +++ b/api/src/Kurs.Platform.Application/ListForms/ListFormSelectAppService.cs @@ -214,8 +214,12 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe IsAppliedServerFilter = selectQueryManager.IsAppliedServerFilter, }; - //Widgets verileri gösterilecek ise - result.Widgets = []; + return result; + } + + private async Task> GetWidgetsAsync(ListForm listForm) + { + var Widgets = new List(); if (!listForm.WidgetsJson.IsNullOrWhiteSpace()) { @@ -224,6 +228,9 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe { if (!string.IsNullOrWhiteSpace(widget.SqlQuery)) { + + var (dynamicDataRepository, connectionString, dataSourceType) = await dynamicDataManager.GetAsync(listForm.IsTenant, listForm.DataSourceCode); + var w = new WidgetDto { ColGap = widget.ColGap, @@ -253,12 +260,12 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe } - result.Widgets.Add(w); + Widgets.Add(w); } } } - return result; + return Widgets; } public async Task GetGridAsync(string ListFormCode) @@ -287,7 +294,8 @@ public class ListFormSelectAppService : PlatformAppService, IListFormSelectAppSe var result = new GridDto { GridOptions = ObjectMapper.Map(listForm), - ColumnFormats = ObjectMapper.Map, List>(fields) + ColumnFormats = ObjectMapper.Map, List>(fields), + Widgets = await GetWidgetsAsync(listForm) }; var queryParameters = httpContextAccessor.HttpContext.Request.Query.ToDictionary(x => x.Key, x => x.Value); diff --git a/ui/Kurs.Platform.Ui.Dockerfile b/ui/Kurs.Platform.Ui.Dockerfile index adf7ab15..57aa2bdd 100644 --- a/ui/Kurs.Platform.Ui.Dockerfile +++ b/ui/Kurs.Platform.Ui.Dockerfile @@ -12,5 +12,5 @@ RUN npm i && \ npm install @rollup/rollup-linux-x64-musl --save-dev && \ npm rebuild rollup COPY . . -RUN npm run build -- --mode $ENV +RUN npm run build && node scripts/write-version.js -- --mode $ENV CMD ["npm", "run", "preview"] diff --git a/ui/public/version.json b/ui/public/version.json index b3217b15..318a0103 100644 --- a/ui/public/version.json +++ b/ui/public/version.json @@ -1,6 +1,20 @@ { - "commit": "a913220", + "commit": "acfe803", "releases": [ + { + "version": "1.0.10", + "buildDate": "2025-09-22", + "changeLog": [ + "EditorOptions içerisine DataSource özelliği eklendi" + ] + }, + { + "version": "1.0.9", + "buildDate": "2025-09-21", + "changeLog": [ + "Form komponentinin SelectBox -> lookup bilgisi varsa verileri dolduruyor" + ] + }, { "version": "1.0.8", "buildDate": "2025-09-21", diff --git a/ui/src/proxy/form/models.ts b/ui/src/proxy/form/models.ts index 86e87a01..d56afb23 100644 --- a/ui/src/proxy/form/models.ts +++ b/ui/src/proxy/form/models.ts @@ -31,6 +31,7 @@ export interface SelectListItem { export interface GridDto { columnFormats: ColumnFormatDto[] gridOptions: GridOptionsDto + widgets: WidgetGroupDto[] } // 3 enums diff --git a/ui/src/shared/useListFormCustomDataSource.ts b/ui/src/shared/useListFormCustomDataSource.ts index ea9021cb..f55eec3a 100644 --- a/ui/src/shared/useListFormCustomDataSource.ts +++ b/ui/src/shared/useListFormCustomDataSource.ts @@ -23,7 +23,6 @@ const useListFormCustomDataSource = ({ listFormCode: string, searchParams?: URLSearchParams, cols?: GridColumnData[], - // setWidgetGroups?: (widgetGroups: WidgetGroupDto[]) => void, ) => { const store: any = new CustomStore({ key: gridOptions.keyFieldName, @@ -139,8 +138,6 @@ const useListFormCustomDataSource = ({ : 'transparent', ) - //Widgets bilgisini store'un custom propertysinde tutuyoruz ki, - store._widgets = response.data.widgets ?? [] const retValue = { data: response.data.data, totalCount: response.data.totalCount, diff --git a/ui/src/views/form/FormButtons.tsx b/ui/src/views/form/FormButtons.tsx index e7791e66..2da72871 100644 --- a/ui/src/views/form/FormButtons.tsx +++ b/ui/src/views/form/FormButtons.tsx @@ -67,8 +67,6 @@ const FormButtons = (props: { getSelectedRowsData, refreshData, getFilter, - extraFilters, - setExtraFilters, }) const handleDelete = async (e: any) => { diff --git a/ui/src/views/form/FormDevExpress.tsx b/ui/src/views/form/FormDevExpress.tsx index 6e602e4b..c4b70586 100644 --- a/ui/src/views/form/FormDevExpress.tsx +++ b/ui/src/views/form/FormDevExpress.tsx @@ -49,7 +49,6 @@ const FormDevExpress = (props: { caption={formGroupItem.caption} > {(formGroupItem.items as SimpleItemWithColData[])?.map((formItem, i) => { - console.log('formItem', formItem.colData) return formItem.editorType2 === PlatformEditorTypes.dxTagBox ? ( { const [currentPage, setCurrentPage] = useState(1) const [pageSize, setPageSize] = useState(20) const [pageSizeOptions, setPageSizeOptions] = useState([]) - const [dataSource, setDataSource] = useState() + const [gridDataSource, setGridDataSource] = useState>() + const [extraFilters, setExtraFilters] = useState([]) + const [layoutCount, setLayoutCount] = useState(4) - // ✅ Lookup cache burada (Card seviyesinde, tüm CardItem’lar ortak kullanır) const { getLookupDataSource } = useLookupDataSource({ listFormCode }) const lookupCache = useRef>(new Map()) @@ -204,7 +208,7 @@ const Card = ({ listFormCode, searchParams }: CardProps) => { } return lookupCache.current.get(key) }, - [getLookupDataSource] + [getLookupDataSource], ) const onPageSizeSelect = ({ value }: Option) => { @@ -222,13 +226,13 @@ const Card = ({ listFormCode, searchParams }: CardProps) => { useEffect(() => { if (gridDto) { - const store = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams) - setDataSource(store) + const dataSource = createSelectDataSource(gridDto.gridOptions, listFormCode, searchParams) + setGridDataSource(dataSource) } }, [gridDto, listFormCode, searchParams, createSelectDataSource]) const loadData = useCallback(() => { - if (!dataSource) return + if (!gridDataSource) return const loadOptions = { skip: (currentPage - 1) * pageSize, @@ -236,91 +240,139 @@ const Card = ({ listFormCode, searchParams }: CardProps) => { requireTotalCount: true, } - dataSource.load(loadOptions).then((res: any) => { + gridDataSource.load(loadOptions).then((res: any) => { setData(res.data) setTotalCount(res.totalCount || 0) }) - }, [dataSource, currentPage, pageSize]) + }, [gridDataSource, currentPage, pageSize]) useEffect(() => { - if (dataSource) { + if (gridDataSource) { loadData() } - }, [dataSource, loadData]) + }, [gridDataSource, loadData]) useEffect(() => { if (!gridDto) return const pagerOptions = gridDto.gridOptions.pagerOptionDto - const allowedSizes = - pagerOptions?.allowedPageSizes - ?.split(',') - .map((s) => Number(s.trim())) - .filter((n) => !isNaN(n) && n > 0) || [10, 20, 50, 100] + const allowedSizes = pagerOptions?.allowedPageSizes + ?.split(',') + .map((s) => Number(s.trim())) + .filter((n) => !isNaN(n) && n > 0) || [10, 20, 50, 100] setPageSizeOptions(allowedSizes.map((size) => ({ value: size, label: `${size} page` }))) }, [gridDto, listFormCode, searchParams]) + // Data güncellendiğinde sayfanın en üstüne kaydır + useEffect(() => { + if (data.length > 0) { + window.scrollTo({ top: 0, behavior: 'smooth' }) + } + }, [data]) + if (!gridDto) return null return ( <> - {data.length === 0 && ( -
-
- -

- Kayıt Bulunamadı -

-

- Görüntülenecek herhangi bir veri yok. -

+ + + +
+
+ + + + + +
- )} -
- {dataSource && - data.map((row, idx) => { - const keyField = gridDto.gridOptions.keyFieldName - const rowId = row[keyField!] - return ( - + {gridDataSource && + data.map((row, idx) => { + const keyField = gridDto.gridOptions.keyFieldName + const rowId = row[keyField!] + + return ( + + ) + })} +
+ + {gridDto.gridOptions.pagerOptionDto?.visible && totalCount > pageSize && ( +
+
+ + Toplam {totalCount} kayıt + + o.value === pageSize)} - options={pageSizeOptions} - onChange={(selected) => onPageSizeSelect(selected as Option)} +
+
- -
- )} + )} + + {data.length === 0 && ( + + //
+ //
+ // + //

+ // Kayıt Bulunamadı + //

+ //

+ // Görüntülenecek herhangi bir veri yok. + //

+ //
+ //
+ )} + ) } diff --git a/ui/src/views/list/Grid.tsx b/ui/src/views/list/Grid.tsx index 83d18852..8103c0f2 100644 --- a/ui/src/views/list/Grid.tsx +++ b/ui/src/views/list/Grid.tsx @@ -7,7 +7,6 @@ import { GridDto, ListFormCustomizationTypeEnum, PlatformEditorTypes, - WidgetGroupDto, } from '@/proxy/form/models' import { getList } from '@/services/form.service' import { @@ -93,7 +92,6 @@ const Grid = (props: GridProps) => { const [columnData, setColumnData] = useState() const [formData, setFormData] = useState() const [mode, setMode] = useState('view') - const [widgetGroups, setWidgetGroups] = useState([]) const [extraFilters, setExtraFilters] = useState([]) const preloadExportLibs = () => { @@ -120,8 +118,6 @@ const Grid = (props: GridProps) => { getSelectedRowsData, refreshData, getFilter, - extraFilters, - setExtraFilters, }) const { filterToolbarData, ...filterData } = useFilters({ @@ -403,10 +399,6 @@ const Grid = (props: GridProps) => { gridRef.current.instance.option('remoteOperations', false) gridRef.current.instance.option('dataSource', undefined) gridRef.current.instance.state(null) - - //bir önceki gridin filtreleri kalmasın - setExtraFilters([]) - setWidgetGroups([]) } const initializeGrid = async () => { @@ -416,6 +408,10 @@ const Grid = (props: GridProps) => { if (refListFormCode.current !== listFormCode) { initializeGrid() + + //bir önceki gridin filtreleri kalmasın + setExtraFilters([]) + defaultSearchParamsFilter.current = null } }, [listFormCode]) @@ -438,6 +434,7 @@ const Grid = (props: GridProps) => { } if (gridDto?.gridOptions.extraFilterDto) { + console.log('extraFilterDto:', gridDto.gridOptions.extraFilterDto) setExtraFilters( gridDto.gridOptions.extraFilterDto.map((f) => ({ fieldName: f.fieldName, @@ -466,35 +463,51 @@ const Grid = (props: GridProps) => { useEffect(() => { const activeFilters = extraFilters.filter((f) => f.value) - let filter: any = null + let base: any = null + if (defaultSearchParamsFilter.current) { + base = JSON.parse(defaultSearchParamsFilter.current) + } - if (activeFilters.length === 1) { - filter = [activeFilters[0].fieldName, activeFilters[0].operator, activeFilters[0].value] - } else if (activeFilters.length > 1) { - filter = activeFilters.reduce((acc, f, idx) => { - if (idx === 0) return [f.fieldName, f.operator, f.value] - return [acc, 'and', [f.fieldName, f.operator, f.value]] + // Default filter tripletlerini çıkar + const baseTriplets = extractSearchParamsFields(base) + + // Extra filter tripletleri hazırla + const extraTriplets = activeFilters.map( + (f) => [f.fieldName, f.operator, f.value] as [string, string, any], + ) + + // Tripletleri birleştir, aynı field+op varsa sonuncuyu al + const merged = [...baseTriplets, ...extraTriplets].reduce( + (acc, cur) => { + const [field, op] = cur + const idx = acc.findIndex((a) => a[0] === field && a[1] === op) + if (idx >= 0) { + acc[idx] = cur // varsa üzerine yaz + } else { + acc.push(cur) + } + return acc + }, + [] as [string, string, any][], + ) + + // Tek filtre varsa direkt yaz + let filter: any = null + if (merged.length === 1) { + filter = merged[0] + } else if (merged.length > 1) { + filter = merged.reduce((acc, f, idx) => { + if (idx === 0) return f + return [acc, 'and', f] }, null as any) } if (filter) { - // hem defaultFilter hem extraFilter birleştir - if (defaultSearchParamsFilter.current) { - const base = JSON.parse(defaultSearchParamsFilter.current) - filter = [base, 'and', filter] - } searchParams?.set('filter', JSON.stringify(filter)) } else { - // sadece default filter kalsın - if (defaultSearchParamsFilter.current) { - searchParams?.set('filter', defaultSearchParamsFilter.current) - } else { - searchParams?.delete('filter') - } + searchParams?.delete('filter') } - //console.log('Filter Durumu:', filter, decodeURIComponent(searchParams?.toString())) - gridRef.current?.instance.refresh() }, [extraFilters]) @@ -594,7 +607,7 @@ const Grid = (props: GridProps) => { return ( <> - + {!isSubForm && ( @@ -629,15 +642,6 @@ const Grid = (props: GridProps) => { focusedRowEnabled={gridDto.gridOptions.columnOptionDto?.focusedRowEnabled} showColumnHeaders={gridDto.gridOptions.columnOptionDto?.showColumnHeaders} filterSyncEnabled={true} - onContentReady={(e) => { - const ds = e.component.getDataSource() - if (!ds) return - - const store = ds.store() as any - if (store._widgets) { - setWidgetGroups(store._widgets) - } - }} onSelectionChanged={onSelectionChanged} onInitNewRow={onInitNewRow} onCellPrepared={onCellPrepared} diff --git a/ui/src/views/list/useToolbar.tsx b/ui/src/views/list/useToolbar.tsx index ad6be9fd..1d5ed5e7 100644 --- a/ui/src/views/list/useToolbar.tsx +++ b/ui/src/views/list/useToolbar.tsx @@ -24,8 +24,6 @@ const useToolbar = ({ getSelectedRowsData, refreshData, getFilter, - extraFilters, - setExtraFilters, }: { gridDto?: GridDto listFormCode: string @@ -33,8 +31,6 @@ const useToolbar = ({ getSelectedRowsData: () => any refreshData: () => void getFilter: () => void - extraFilters: GridExtraFilterState[] - setExtraFilters: React.Dispatch> }): { toolbarData: ToolbarItem[] toolbarModalData: ToolbarModalData | undefined