From b53a4243ab7dd8717a5f66b471ded4d9051efa8e 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, 13 Jul 2026 16:51:13 +0300 Subject: [PATCH] =?UTF-8?q?AiBot=20Tenantl=C4=B1=20ve=20MenuManager=20d?= =?UTF-8?q?=C3=BCzenlendi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AiBots/AiBotAppService.cs | 38 ++++++++++++++++--- ui/src/views/menu/MenuItemComponent.tsx | 34 ++++++++++++++--- ui/src/views/menu/MenuManager.tsx | 36 +++++++++++++++++- ui/src/views/menu/SortableMenuTree.tsx | 12 +++++- 4 files changed, 108 insertions(+), 12 deletions(-) diff --git a/api/src/Sozsoft.Platform.Application/AiBots/AiBotAppService.cs b/api/src/Sozsoft.Platform.Application/AiBots/AiBotAppService.cs index a50feb6..9b2b92e 100644 --- a/api/src/Sozsoft.Platform.Application/AiBots/AiBotAppService.cs +++ b/api/src/Sozsoft.Platform.Application/AiBots/AiBotAppService.cs @@ -6,6 +6,7 @@ using Volo.Abp.Application.Services; using Volo.Abp.Domain.Repositories; using System.Threading.Tasks; using System.Linq; +using System.Collections.Generic; namespace Sozsoft.Platform.AiBots; @@ -25,16 +26,31 @@ public class AiBotAppService : CrudAppService< { await CheckGetListPolicyAsync(); - var query = await CreateFilteredQueryAsync(input); - if (CurrentTenant.IsAvailable && !string.IsNullOrWhiteSpace(CurrentTenant.Name)) { var tenantName = CurrentTenant.Name; - query = query.Where(aiBot => - string.IsNullOrWhiteSpace(aiBot.Tenants) || - aiBot.Tenants.Contains($"\"{tenantName}\"")); + List tenantEntities; + + using (CurrentTenant.Change(null)) + { + var hostQuery = await CreateFilteredQueryAsync(input); + tenantEntities = await AsyncExecuter.ToListAsync(hostQuery); + } + + var filteredQuery = tenantEntities + .Where(aiBot => IsAvailableForTenant(aiBot.Tenants, tenantName)) + .AsQueryable(); + + var tenantTotalCount = filteredQuery.LongCount(); + filteredQuery = ApplySorting(filteredQuery, input); + filteredQuery = ApplyPaging(filteredQuery, input); + + var tenantDtos = await MapToGetListOutputDtosAsync(filteredQuery.ToList()); + + return new PagedResultDto(tenantTotalCount, tenantDtos); } + var query = await CreateFilteredQueryAsync(input); var totalCount = await AsyncExecuter.CountAsync(query); query = ApplySorting(query, input); query = ApplyPaging(query, input); @@ -44,5 +60,17 @@ public class AiBotAppService : CrudAppService< return new PagedResultDto(totalCount, dtos); } + + private static bool IsAvailableForTenant(string tenants, string tenantName) + { + if (string.IsNullOrWhiteSpace(tenants)) + { + return true; + } + + return tenants + .Split('|', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Any(name => string.Equals(name, tenantName, StringComparison.OrdinalIgnoreCase)); + } } diff --git a/ui/src/views/menu/MenuItemComponent.tsx b/ui/src/views/menu/MenuItemComponent.tsx index 37e61bc..ed21feb 100644 --- a/ui/src/views/menu/MenuItemComponent.tsx +++ b/ui/src/views/menu/MenuItemComponent.tsx @@ -1,4 +1,4 @@ -import React, { useState } from 'react' +import React, { useEffect, useState } from 'react' import { useSortable } from '@dnd-kit/sortable' import { CSS } from '@dnd-kit/utilities' import { MenuItem } from '@/proxy/menus/menu' @@ -19,7 +19,7 @@ import { import { Field, FieldProps, Form, Formik } from 'formik' import { SelectBoxOption } from '@/types/shared' import * as Yup from 'yup' -import { FaQuestionCircle, FaPlus, FaTrashAlt } from 'react-icons/fa' +import { FaChevronDown, FaChevronRight, FaQuestionCircle, FaPlus, FaTrashAlt } from 'react-icons/fa' import { MenuDto } from '@/proxy/menus/models' interface MenuItemComponentProps { @@ -30,6 +30,7 @@ interface MenuItemComponentProps { isDragOverlay?: boolean refetch: () => void permissions: SelectBoxOption[] + expansionCommand: { expanded: boolean; version: number } } export const MenuItemComponent: React.FC = ({ @@ -40,6 +41,7 @@ export const MenuItemComponent: React.FC = ({ isDragOverlay = false, refetch, permissions, + expansionCommand, }) => { const { translate } = useLocalization() @@ -75,6 +77,10 @@ export const MenuItemComponent: React.FC = ({ const [isModalOpen, setIsModalOpen] = useState(false) const [modalMode, setModalMode] = useState<'create' | 'edit'>('create') + useEffect(() => { + setIsExpanded(expansionCommand.expanded) + }, [expansionCommand.expanded, expansionCommand.version]) + const getCreateInitialValues = (): Partial => ({ code: '', displayName: '', @@ -106,8 +112,9 @@ export const MenuItemComponent: React.FC = ({ const [formData, setFormData] = useState>(getCreateInitialValues()) - const toggleExpanded = () => { - if (!isDesignMode) setIsExpanded(!isExpanded) + const toggleExpanded = (event?: React.MouseEvent) => { + event?.stopPropagation() + setIsExpanded((current) => !current) } const openCreateModal = () => { @@ -146,6 +153,23 @@ export const MenuItemComponent: React.FC = ({ `} {...(isDesignMode ? { ...attributes, ...listeners } : { onClick: toggleExpanded })} > + {isDesignMode && + (item.children && item.children.length > 0 ? ( + +
+ + +
+