menumanager çağırınca abpconfig tekrar çağrılsın menü düzenlensin

This commit is contained in:
Sedat ÖZTÜRK 2025-06-26 17:59:53 +03:00
parent b2dc2251d8
commit 35e4957cc3
9 changed files with 129 additions and 58 deletions

View file

@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging;
using Volo.Abp.Application.Dtos;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using static Kurs.Platform.Data.Seeds.SeedConsts;
namespace Kurs.Platform.Menus;
@ -28,6 +29,10 @@ public class MenuAppService : CrudAppService<
{
_menuRepository = menuRepository;
_repositoryKey = languageKeyRepository;
CreatePolicyName = $"{AppCodes.Menus.Menu}.Create";
UpdatePolicyName = $"{AppCodes.Menus.Menu}.Update";
DeletePolicyName = $"{AppCodes.Menus.Menu}.Delete";
}
public override async Task<PagedResultDto<MenuDto>> GetListAsync(PagedAndSortedResultRequestDto input)
@ -81,6 +86,8 @@ public class MenuAppService : CrudAppService<
public override async Task<MenuDto> CreateAsync(MenuDto input)
{
await CheckCreatePolicyAsync();
var keyExists = await _repositoryKey.AnyAsync(
a => a.Key == input.DisplayName &&
a.ResourceName == PlatformConsts.AppName);
@ -98,6 +105,8 @@ public class MenuAppService : CrudAppService<
public override async Task<MenuDto> UpdateAsync(Guid id, MenuDto input)
{
await CheckUpdatePolicyAsync();
var key = await _repositoryKey.FirstOrDefaultAsync(
a => a.Key == input.DisplayName &&
a.ResourceName == PlatformConsts.AppName);
@ -115,8 +124,44 @@ public class MenuAppService : CrudAppService<
return await base.UpdateAsync(id, input);
}
public async Task<List<MenuDto>> UpdateAllAsync(List<MenuDto> inputs)
{
await CheckUpdatePolicyAsync();
var result = new List<MenuDto>();
foreach (var input in inputs)
{
if (input.Id == Guid.Empty)
{
throw new ArgumentException("MenuDto içinde geçerli bir Id bulunmalıdır.");
}
var key = await _repositoryKey.FirstOrDefaultAsync(
a => a.Key == input.DisplayName &&
a.ResourceName == PlatformConsts.AppName);
if (key is null)
{
await _repositoryKey.InsertAsync(new LanguageKey
{
Key = input.DisplayName,
ResourceName = PlatformConsts.AppName
});
}
var updated = await base.UpdateAsync(input.Id, input);
result.Add(updated);
}
return result;
}
public override async Task DeleteAsync(Guid id)
{
await CheckDeletePolicyAsync();
var menu = await _menuRepository.GetAsync(id);
if (menu != null)
{

View file

@ -82,7 +82,7 @@ define(['./workbox-54d0af47'], (function (workbox) { 'use strict';
"revision": "3ca0b8505b4bec776b69afdba2768812"
}, {
"url": "index.html",
"revision": "0.scg6n9r90k8"
"revision": "0.hld5cocdcl"
}], {});
workbox.cleanupOutdatedCaches();
workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), {

View file

@ -27,14 +27,17 @@ const HorizontalMenuContent = ({ manuVariant }: HorizontalMenuContentProps) => {
{navigationConfig.map((nav) => {
if (nav.type === NAV_ITEM_TYPE_TITLE || nav.type === NAV_ITEM_TYPE_COLLAPSE) {
return (
<PermissionCheck key={nav.key} permissions={nav.authority}>
<PermissionCheck
key={nav.key || `nav-${nav.path || Math.random()}`}
permissions={nav.authority}
>
<Dropdown
trigger="hover"
renderTitle={<HorizontalMenuItem manuVariant={manuVariant} nav={nav} />}
>
{nav.subMenu.map((secondarySubNav) => (
<PermissionCheck
key={secondarySubNav.key}
key={secondarySubNav.key || `sec-${secondarySubNav.path || Math.random()}`}
permissions={secondarySubNav.authority}
>
{secondarySubNav.subMenu.length > 0 ? (
@ -42,23 +45,34 @@ const HorizontalMenuContent = ({ manuVariant }: HorizontalMenuContentProps) => {
title={
<div className="flex items-center">
<HorizontalMenuIcon icon={secondarySubNav.icon} />
<span>
{t(secondarySubNav.translateKey, secondarySubNav.title)}
</span>
<span>{t(secondarySubNav.translateKey, secondarySubNav.title)}</span>
</div>
}
>
{secondarySubNav.subMenu.map((tertiarySubNav) => (
<PermissionCheck
key={tertiarySubNav.key}
key={
tertiarySubNav.key || `ter-${tertiarySubNav.path || Math.random()}`
}
permissions={tertiarySubNav.authority}
>
<HorizontalMenuDropdownItem nav={tertiarySubNav} />
<HorizontalMenuDropdownItem
key={
tertiarySubNav.key ||
`ter-item-${tertiarySubNav.path || Math.random()}`
}
nav={tertiarySubNav}
/>
</PermissionCheck>
))}
</Dropdown.Menu>
) : (
<HorizontalMenuDropdownItem key={secondarySubNav.key} nav={secondarySubNav} />
<HorizontalMenuDropdownItem
key={
secondarySubNav.key || `sec-item-${secondarySubNav.path || Math.random()}`
}
nav={secondarySubNav}
/>
)}
</PermissionCheck>
))}

View file

@ -5,33 +5,43 @@ import apiService, { Config } from '@/services/api.service'
export class MenuService {
apiName = 'Default'
// create = (input: MenuDto, config?: Partial<Rest.Config>) =>
// this.restService.request<any, MenuDto>(
// {
// method: 'POST',
// url: '/api/app/menu',
// body: input,
// },
// { apiName: this.apiName, ...config },
// )
update = (id: string, input: MenuDto, config?: Partial<Config>) =>
apiService.fetchData<MenuDto, MenuDto>(
{
method: 'PUT',
url: `/api/app/menu/${id}`,
data: input,
},
{ apiName: this.apiName, ...config },
)
// delete = (id: string, config?: Partial<Rest.Config>) =>
// this.restService.request<any, void>(
// {
// method: 'DELETE',
// url: `/api/app/menu/${id}`,
// },
// { apiName: this.apiName, ...config },
// )
create = (input: MenuDto, config?: Partial<Config>) =>
apiService.fetchData<MenuDto, MenuDto>(
{
method: 'POST',
url: '/api/app/menu',
data: input,
},
{ apiName: this.apiName, ...config },
)
// get = (id: string, config?: Partial<Rest.Config>) =>
// this.restService.request<any, MenuDto>(
// {
// method: 'GET',
// url: `/api/app/menu/${id}`,
// },
// { apiName: this.apiName, ...config },
// )
delete = (id: string, config?: Partial<Config>) =>
apiService.fetchData<void>(
{
method: 'DELETE',
url: `/api/app/menu/${id}`,
},
{ apiName: this.apiName, ...config },
)
get = (id: string, config?: Partial<Config>) =>
apiService.fetchData<MenuDto>(
{
method: 'GET',
url: `/api/app/menu/${id}`,
},
{ apiName: this.apiName, ...config },
)
getList = (input: PagedAndSortedResultRequestDto, config?: Partial<Config>) =>
apiService.fetchData<PagedResultDto<MenuDto>, PagedAndSortedResultRequestDto>(
@ -47,15 +57,15 @@ export class MenuService {
{ apiName: this.apiName, ...config },
)
// update = (id: string, input: MenuDto, config?: Partial<Rest.Config>) =>
// this.restService.request<any, MenuDto>(
// {
// method: 'PUT',
// url: `/api/app/menu/${id}`,
// body: input,
// },
// { apiName: this.apiName, ...config },
// )
updateAll = (inputs: MenuDto[], config?: Partial<Config>) =>
apiService.fetchData<void, MenuDto[]>(
{
method: 'PUT',
url: '/api/app/menu/all',
data: inputs,
},
{ apiName: this.apiName, ...config },
)
}
export const getMenus = async (skipCount = 0, maxResultCount = 1000, sorting = 'order') => {

View file

@ -1,11 +1,13 @@
import { MenuApiResponse, MenuItem } from '@/@types/menu'
import { getMenus } from '@/services/menu.service'
import { MenuItem } from '@/@types/menu'
import { getMenus, MenuService } from '@/services/menu.service'
import { useStoreActions } from '@/store/store'
import { useState, useEffect } from 'react'
export const useMenuData = () => {
const [menuItems, setMenuItems] = useState<MenuItem[]>([])
const [loading, setLoading] = useState(true)
const [error, setError] = useState<string | null>(null)
const { getConfig } = useStoreActions((a) => a.abpConfig)
const buildHierarchy = (items: MenuItem[]): MenuItem[] => {
const itemMap = new Map<string, MenuItem>()
@ -58,7 +60,6 @@ export const useMenuData = () => {
const hierarchicalMenu = buildHierarchy(response.data.items)
setMenuItems(hierarchicalMenu)
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load menu data')
} finally {
@ -67,6 +68,8 @@ export const useMenuData = () => {
}
const saveMenuData = async (updatedMenuItems: MenuItem[]) => {
const menuService = new MenuService()
try {
// Flatten the hierarchy for API
const flatten = (items: MenuItem[], parentCode: string | null = null): MenuItem[] => {
@ -86,14 +89,9 @@ export const useMenuData = () => {
})
return result
}
const flatMenuItems = flatten(updatedMenuItems)
// Simulate API call
await new Promise((resolve) => setTimeout(resolve, 1000))
console.log('Saving menu data:', flatMenuItems)
// In real implementation: await api.saveMenus(flatMenuItems);
const items = flatten(updatedMenuItems)
await menuService.updateAll(items)
getConfig(false)
return { success: true }
} catch (err) {

View file

@ -45,7 +45,7 @@ function FormFieldTabPivotSetting({
initialValues={initialValues}
validationSchema={schema}
onSubmit={async (values, formikHelpers) => {
console.log(values)
//console.log(values)
await onSubmit(ListFormFieldEditTabs.PivotSettingsForm, values, formikHelpers)
}}
>

View file

@ -230,7 +230,7 @@ const BlogManagement = () => {
const handleEditCategory = (category: BlogCategory) => {
setEditingCategory(category)
console.log(category)
//console.log(category)
setCategoryModalVisible(true)
}

View file

@ -25,7 +25,6 @@ export const MenuManager = () => {
setSaveMessage(null)
await saveMenuData(menuItems)
setSaveMessage({ type: 'success', text: 'Menu configuration saved successfully!' })
setTimeout(() => setSaveMessage(null), 3000)
} catch (err) {

View file

@ -186,7 +186,12 @@ export const SortableMenuTree: React.FC<SortableMenuTreeProps> = ({
const renderMenuItem = (item: MenuItem, depth: number = 0): React.ReactNode => {
return (
<MenuItemComponent key={item.id} item={item} isDesignMode={isDesignMode} depth={depth}>
<MenuItemComponent
key={item.id || `temp-${Math.random().toString(36).substr(2, 9)}`}
item={item}
isDesignMode={isDesignMode}
depth={depth}
>
{item.children && item.children.length > 0 && (
<div className="ml-4">
{item.children.map((child) => renderMenuItem(child, depth + 1))}