From c0aec4362024d6e7fd2530f26888c8d02a1ae32e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sedat=20=C3=96zt=C3=BCrk?= Date: Sat, 11 Oct 2025 21:04:22 +0300 Subject: [PATCH] =?UTF-8?q?ListForm=20Manage=20ve=20AppServis=20g=C3=BCnce?= =?UTF-8?q?llemeleri?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ListFormCustomizationAppService.cs | 6 +- .../ListFormFieldsAppService.cs | 11 +- .../Administration/ListFormsAppService.cs | 2 +- .../Menu/MenuAppService.cs | 1 - .../Seeds/HostData.json | 12 +- .../ListForms/ListFormAuthorizationManager.cs | 2 + .../Permissions/PermissionCrudValueObject.cs | 4 + ui/src/views/list/useFilters.tsx | 119 +++++++++++++----- ui/src/views/list/useToolbar.tsx | 48 ++++--- 9 files changed, 141 insertions(+), 64 deletions(-) diff --git a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormCustomizationAppService.cs b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormCustomizationAppService.cs index 629e03b4..268dc39d 100644 --- a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormCustomizationAppService.cs +++ b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormCustomizationAppService.cs @@ -8,10 +8,11 @@ using Kurs.Platform.ListForms.Customization; using Microsoft.AspNetCore.Authorization; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; +using static Kurs.Platform.PlatformConsts; namespace Kurs.Platform.ListForms.Administration; -[Authorize(PlatformConsts.AppCodes.Listforms.Listform)] +[Authorize(AppCodes.Listforms.Listform)] public class ListFormCustomizationAppService : CrudAppService _repository ) : base(_repository) { + CreatePolicyName = $"{AppCodes.Listforms.Listform}.Create"; + UpdatePolicyName = $"{AppCodes.Listforms.Listform}.Update"; + DeletePolicyName = $"{AppCodes.Listforms.Listform}.Delete"; } protected override async Task> CreateFilteredQueryAsync(ListFormCustomizationRequestDto input) diff --git a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormFieldsAppService.cs b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormFieldsAppService.cs index 2346add2..cdad9a61 100644 --- a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormFieldsAppService.cs +++ b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormFieldsAppService.cs @@ -8,6 +8,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; +using static Kurs.Platform.PlatformConsts; namespace Kurs.Platform.ListForms.Administration; @@ -26,6 +27,10 @@ public class ListFormFieldsAppService : CrudAppService< ) : base(_repository) { RepoListForm = _repoListForm; + + CreatePolicyName = $"{AppCodes.Listforms.Listform}.Create"; + UpdatePolicyName = $"{AppCodes.Listforms.Listform}.Update"; + DeletePolicyName = $"{AppCodes.Listforms.Listform}.Delete"; } protected override async Task> CreateFilteredQueryAsync(ListFormFieldRequestDto input) @@ -99,9 +104,9 @@ public class ListFormFieldsAppService : CrudAppService< input.PermissionJson = JsonSerializer.Serialize(new ListFormFieldPermissionDto { - R = listFormPermissions.R, - C = listFormPermissions.C, - U = listFormPermissions.U, + R = listFormPermissions?.R, + C = listFormPermissions?.C, + U = listFormPermissions?.U, E = true }); } diff --git a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormsAppService.cs b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormsAppService.cs index 6ea9b0f1..42072bf9 100644 --- a/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormsAppService.cs +++ b/api/src/Kurs.Platform.Application/ListForms/Administration/ListFormsAppService.cs @@ -35,7 +35,7 @@ public class ListFormsAppService : CrudAppService< public async Task GetByListFormCodeAsync(string listFormCode) { - bool canAccess = await authManager.CanAccess(listFormCode, AuthorizationTypeEnum.Read); + bool canAccess = await authManager.CanAccess(listFormCode, AuthorizationTypeEnum.Update); if (!canAccess) { throw new UserFriendlyException(L[AppErrorCodes.NoAuth]); diff --git a/api/src/Kurs.Platform.Application/Menu/MenuAppService.cs b/api/src/Kurs.Platform.Application/Menu/MenuAppService.cs index 892cb3a5..45f30a83 100644 --- a/api/src/Kurs.Platform.Application/Menu/MenuAppService.cs +++ b/api/src/Kurs.Platform.Application/Menu/MenuAppService.cs @@ -157,7 +157,6 @@ public class MenuAppService : CrudAppService< return result; } - public override async Task DeleteAsync(Guid id) { await CheckDeletePolicyAsync(); diff --git a/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json b/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json index 30f43f7e..68d3133f 100644 --- a/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json +++ b/api/src/Kurs.Platform.DbMigrator/Seeds/HostData.json @@ -17702,7 +17702,7 @@ "MultiTenancySide": 2 }, { - "GroupName": "App.Saas", + "GroupName": "App.Administration", "Name": "App.Definitions.Sector", "ParentName": null, "DisplayName": "App.Definitions.Sector", @@ -17710,7 +17710,7 @@ "MultiTenancySide": 3 }, { - "GroupName": "App.Saas", + "GroupName": "App.Administration", "Name": "App.Definitions.Sector.Create", "ParentName": "App.Definitions.Sector", "DisplayName": "Create", @@ -17718,7 +17718,7 @@ "MultiTenancySide": 3 }, { - "GroupName": "App.Saas", + "GroupName": "App.Administration", "Name": "App.Definitions.Sector.Update", "ParentName": "App.Definitions.Sector", "DisplayName": "Update", @@ -17726,7 +17726,7 @@ "MultiTenancySide": 3 }, { - "GroupName": "App.Saas", + "GroupName": "App.Administration", "Name": "App.Definitions.Sector.Delete", "ParentName": "App.Definitions.Sector", "DisplayName": "Delete", @@ -17734,7 +17734,7 @@ "MultiTenancySide": 3 }, { - "GroupName": "App.Saas", + "GroupName": "App.Administration", "Name": "App.Definitions.Sector.Export", "ParentName": "App.Definitions.Sector", "DisplayName": "Export", @@ -17742,7 +17742,7 @@ "MultiTenancySide": 3 }, { - "GroupName": "App.Saas", + "GroupName": "App.Administration", "Name": "App.Definitions.Sector.Import", "ParentName": "App.Definitions.Sector", "DisplayName": "Import", diff --git a/api/src/Kurs.Platform.Domain/ListForms/ListFormAuthorizationManager.cs b/api/src/Kurs.Platform.Domain/ListForms/ListFormAuthorizationManager.cs index 3fcfedac..6733dc45 100644 --- a/api/src/Kurs.Platform.Domain/ListForms/ListFormAuthorizationManager.cs +++ b/api/src/Kurs.Platform.Domain/ListForms/ListFormAuthorizationManager.cs @@ -55,6 +55,8 @@ public class ListFormAuthorizationManager : PlatformDomainService, IListFormAuth AuthorizationTypeEnum.Update => permissions.U, AuthorizationTypeEnum.Create => permissions.C, AuthorizationTypeEnum.Delete => permissions.D, + AuthorizationTypeEnum.Import => permissions.I, + AuthorizationTypeEnum.Export => permissions.E, _ => permissions.R, }; diff --git a/api/src/Kurs.Platform.Domain/Permissions/PermissionCrudValueObject.cs b/api/src/Kurs.Platform.Domain/Permissions/PermissionCrudValueObject.cs index 8bf7f757..2eff4d32 100644 --- a/api/src/Kurs.Platform.Domain/Permissions/PermissionCrudValueObject.cs +++ b/api/src/Kurs.Platform.Domain/Permissions/PermissionCrudValueObject.cs @@ -9,6 +9,8 @@ public class PermissionCrudValueObject : ValueObject public string R { get; set; } public string U { get; set; } public string D { get; set; } + public string I { get; set; } + public string E { get; set; } protected override IEnumerable GetAtomicValues() { @@ -16,5 +18,7 @@ public class PermissionCrudValueObject : ValueObject yield return R; yield return U; yield return D; + yield return I; + yield return E; } } diff --git a/ui/src/views/list/useFilters.tsx b/ui/src/views/list/useFilters.tsx index 883bd8f2..6d3c1d0c 100644 --- a/ui/src/views/list/useFilters.tsx +++ b/ui/src/views/list/useFilters.tsx @@ -9,9 +9,10 @@ import { useLocalization } from '@/utils/hooks/useLocalization' import DataGrid from 'devextreme-react/data-grid' import PivotGrid from 'devextreme-react/pivot-grid' import { ToolbarItem } from 'devextreme/ui/data_grid_types' +import dxDataGrid from 'devextreme/ui/data_grid' +import dxPivotGrid from 'devextreme/ui/pivot_grid' import { Dispatch, MutableRefObject, SetStateAction, useEffect, useState } from 'react' import { setGridPanelColor } from './Utils' -import { useNavigate } from 'react-router-dom' import { usePermission } from '@/utils/hooks/usePermission' import { usePWA } from '@/utils/hooks/usePWA' import { ROUTES_ENUM } from '@/routes/route.constant' @@ -21,6 +22,75 @@ export interface ISelectBoxData { label?: string } +// Grid tipini kontrol eden yardımcı fonksiyonlar +const isDataGrid = (grid: dxDataGrid | dxPivotGrid): grid is dxDataGrid => { + return 'clearFilter' in grid +} + +const getToolbarItems = (grid: dxDataGrid | dxPivotGrid): any[] => { + if (isDataGrid(grid)) { + const toolbarOptions = grid.option('toolbar') + return toolbarOptions?.items || [] + } + return [] +} + +const setToolbarItemValue = (grid: dxDataGrid | dxPivotGrid, itemName: string, value: any) => { + if (isDataGrid(grid)) { + const toolbarOptions = grid.option('toolbar') + if (toolbarOptions?.items) { + const index = toolbarOptions.items.findIndex((item: any) => item.name === itemName) + if (index > -1 && toolbarOptions.items[index]) { + const item = toolbarOptions.items[index] as any + if (item.options) { + item.options.value = value + grid.option('toolbar', toolbarOptions) + } + } + } + } +} + +const setToolbarItemItems = (grid: dxDataGrid | dxPivotGrid, itemName: string, items: any[]) => { + if (isDataGrid(grid)) { + const toolbarOptions = grid.option('toolbar') + if (toolbarOptions?.items) { + const index = toolbarOptions.items.findIndex((item: any) => item.name === itemName) + if (index > -1 && toolbarOptions.items[index]) { + const item = toolbarOptions.items[index] as any + if (item.options) { + item.options.items = items + grid.option('toolbar', toolbarOptions) + } + } + } + } +} + +const clearGridFilter = (grid: dxDataGrid | dxPivotGrid) => { + if (isDataGrid(grid)) { + grid.clearFilter() + } +} + +const setFilterPanelVisible = (grid: dxDataGrid | dxPivotGrid, visible: boolean) => { + if (isDataGrid(grid)) { + grid.option('filterPanel', { visible }) + } +} + +const setFilterValue = (grid: dxDataGrid | dxPivotGrid, value: any) => { + if (isDataGrid(grid)) { + grid.option('filterValue', value) + } +} + +const resetGridState = (grid: dxDataGrid | dxPivotGrid) => { + if (isDataGrid(grid)) { + grid.state(null) + } +} + const useFilters = ({ gridDto, gridRef, @@ -58,7 +128,6 @@ const useFilters = ({ const filteredGridPanelColor = 'rgba(10, 200, 10, 0.5)' // kullanici tanimli filtre ile filtrelenmis gridin paneline ait renk const grdOpt = gridDto?.gridOptions - const navigate = useNavigate() const getFilters = async () => { const response = await getListFormCustomization( @@ -75,12 +144,8 @@ const useFilters = ({ const grid = gridRef?.current?.instance if (grid) { - const toolbarItems = grid.option('toolbar.items') as ToolbarItem[] - const index = toolbarItems?.findIndex((a) => a.name === 'selectCustomFilters') - if (index > -1) { - grid.option(`toolbar.items.${index}.options.value`, '') - grid.option(`toolbar.items.${index}.options.items`, mappedFilters) - } + setToolbarItemValue(grid, 'selectCustomFilters', '') + setToolbarItemItems(grid, 'selectCustomFilters', mappedFilters) } } @@ -141,7 +206,7 @@ const useFilters = ({ }) } - if (checkPermission(gridDto?.gridOptions.permissionDto.u)) { + if (checkPermission("App.ListForms.ListForm.Update")) { menus.push({ text: translate('::ListForms.ListForm.Manage'), id: 'openManage', @@ -192,32 +257,24 @@ const useFilters = ({ return } - grid.clearFilter() - grid.option('filterPanel.visible', false) + clearGridFilter(grid) + setFilterPanelVisible(grid, false) setGridPanelColor('transparent') - const toolbarItems = grid.option('toolbar.items') as ToolbarItem[] - const index = toolbarItems?.findIndex((a) => a.name === 'selectCustomFilters') - if (index > -1) { - grid.option(`toolbar.items.${index}.options.value`, '') - } + setToolbarItemValue(grid, 'selectCustomFilters', '') } else if (itemData.id === 'resetGridState') { // state ye kaydedilen grid ayarlarini siler ve gridi resetler const grid = gridRef.current?.instance if (!grid) { return } - grid.state(null) + resetGridState(grid) - grid.clearFilter() - grid.option('filterPanel.visible', false) + clearGridFilter(grid) + setFilterPanelVisible(grid, false) setGridPanelColor('transparent') - const toolbarItems = grid.option('toolbar.items') as ToolbarItem[] - const index = toolbarItems?.findIndex((a) => a.name === 'selectCustomFilters') - if (index > -1) { - grid.option(`toolbar.items.${index}.options.value`, '') - } + setToolbarItemValue(grid, 'selectCustomFilters', '') } else if (itemData.id === 'importManager') { // import modal aç setIsImportModalOpen(true) @@ -259,12 +316,12 @@ const useFilters = ({ try { const filter = filters.find((a) => a.id === e.value) if (filter) { - grid.option('filterValue', JSON.parse(filter.customizationData)) - grid.option('filterPanel.visible', true) + setFilterValue(grid, JSON.parse(filter.customizationData)) + setFilterPanelVisible(grid, true) setGridPanelColor(filteredGridPanelColor) } else { - grid.clearFilter() - grid.option('filterPanel.visible', false) + clearGridFilter(grid) + setFilterPanelVisible(grid, false) setGridPanelColor('transparent') } @@ -282,11 +339,7 @@ const useFilters = ({ }, ) } finally { - const toolbarItems = grid.option('toolbar.items') as ToolbarItem[] - const index = toolbarItems?.findIndex((a) => a.name === 'selectCustomFilters') - if (index > -1) { - grid.option(`toolbar.items.${index}.options.value`, value) - } + setToolbarItemValue(grid, 'selectCustomFilters', value) } }, }, diff --git a/ui/src/views/list/useToolbar.tsx b/ui/src/views/list/useToolbar.tsx index 42584a5d..0e7e1704 100644 --- a/ui/src/views/list/useToolbar.tsx +++ b/ui/src/views/list/useToolbar.tsx @@ -53,6 +53,25 @@ const useToolbar = ({ return } + // Add searchPanel + if (grdOpt.searchPanelDto?.visible) { + items.push({ + locateInMenu: 'auto', + showText: 'inMenu', + name: 'searchPanel', + }) + } + + items.push({ + widget: 'dxButton', + name: 'refreshButton', + options: { + icon: 'refresh', + onClick: refreshData, + }, + location: 'after', + }) + // field chooser panel if (grdOpt.columnOptionDto?.columnChooserEnabled) { items.push({ @@ -62,6 +81,16 @@ const useToolbar = ({ }) } + // Add InsertNewRecord button + if (grdOpt.editingOptionDto?.allowAdding && checkPermission(grdOpt.permissionDto?.c)) { + items.push({ + locateInMenu: 'auto', + showText: 'inMenu', + name: 'addRowButton', + location: 'after', + }) + } + // Add group panel if (grdOpt.groupPanelDto?.visible) { items.push({ @@ -171,16 +200,6 @@ const useToolbar = ({ } } - // Add InsertNewRecord button - if (grdOpt.editingOptionDto?.allowAdding && checkPermission(grdOpt.permissionDto?.c)) { - items.push({ - locateInMenu: 'auto', - showText: 'inMenu', - name: 'addRowButton', - location: 'after', - }) - } - // #region Toolbar icin kullanici tanimli dinamik butonlari ekler for (let i = 0; i < grdOpt.commandColumnDto.length; i++) { const action = grdOpt.commandColumnDto[i] @@ -248,15 +267,6 @@ const useToolbar = ({ } // #endregion - // Add searchPanel - if (grdOpt.searchPanelDto?.visible) { - items.push({ - locateInMenu: 'auto', - showText: 'inMenu', - name: 'searchPanel', - }) - } - // batch editing icin kaydet ve geri al butonu if ( grdOpt.editingOptionDto?.allowUpdating &&