🖼️ style: Improve Marketplace & Sharing Dialog UI

feat: Enhance CategoryTabs and Marketplace components for better responsiveness and navigation

feat: Refactor AgentCard and AgentGrid components for improved layout and accessibility

feat: Implement animated category transitions in AgentMarketplace and update NewChat component layout

feat: Refactor UI components for improved styling and accessibility in sharing dialogs

refactor: remove GenericManagePermissionsDialog and GrantAccessDialog components

- Deleted GenericManagePermissionsDialog and GrantAccessDialog components to streamline sharing functionality.
- Updated ManagePermissionsDialog to utilize AccessRolesPicker directly.
- Introduced UnifiedPeopleSearch for improved people selection experience.
- Enhanced PublicSharingToggle with InfoHoverCard for better user guidance.
- Adjusted AgentPanel to change error status to warning for duplicate agent versions.
- Updated translations to include new keys for search and access management.

feat: Add responsive design for SelectedPrincipalsList and improve layout in GenericGrantAccessDialog

feat: Enhance styling in SelectedPrincipalsList and SearchPicker components for improved UI consistency

feat: Improve PublicSharingToggle component with enhanced styling and accessibility features

feat: Introduce InfoHoverCard component and refactor enums for better organization

feat: Implement infinite scroll for agent grids and enhance performance

- Added `useInfiniteScroll` hook to manage infinite scrolling behavior in agent grids.
- Integrated infinite scroll functionality into `AgentGrid` and `VirtualizedAgentGrid` components.
- Updated `AgentMarketplace` to pass the scroll container to the agent grid components.
- Refactored loading indicators to show a spinner instead of a "Load More" button.
- Created `VirtualizedAgentGrid` component for optimized rendering of agent cards using virtualization.
- Added performance tests for `VirtualizedAgentGrid` to ensure efficient handling of large datasets.
- Updated translations to include new messages for end-of-results scenarios.

chore: Remove unused permission-related UI localization keys

ci: Update Agent model tests to handle duplicate support_contact updates

- Modified tests to ensure that updating an agent with the same support_contact does not create a new version and returns successfully.
- Enhanced verification for partial changes in support_contact, confirming no new version is created when content remains the same.

chore: Address ESLint, clean up unused imports and improve prop definitions in various components

ci: fix tests

ci: update tests

chore: remove unused search localization keys
This commit is contained in:
Marco Beretta 2025-08-04 18:50:54 +02:00 committed by Danny Avila
parent 9585db14ba
commit d82a63642d
No known key found for this signature in database
GPG key ID: BF31EEB2C5CA0956
51 changed files with 2074 additions and 1311 deletions

View file

@ -0,0 +1,91 @@
import { useCallback, useEffect, useRef } from 'react';
import { throttle } from 'lodash';
interface UseInfiniteScrollOptions {
hasNextPage?: boolean;
isFetchingNextPage?: boolean;
fetchNextPage: () => void;
threshold?: number; // Percentage of scroll position to trigger fetch (0-1)
throttleMs?: number; // Throttle delay in milliseconds
}
/**
* Custom hook for implementing infinite scroll functionality
* Detects when user scrolls near the bottom and triggers data fetching
*/
export const useInfiniteScroll = ({
hasNextPage = false,
isFetchingNextPage = false,
fetchNextPage,
threshold = 0.8, // Trigger when 80% scrolled
throttleMs = 200,
}: UseInfiniteScrollOptions) => {
const scrollElementRef = useRef<HTMLElement | null>(null);
// Throttled scroll handler to prevent excessive API calls
const handleScroll = useCallback(
throttle(() => {
const element = scrollElementRef.current;
if (!element) return;
const { scrollTop, scrollHeight, clientHeight } = element;
// Calculate scroll position as percentage
const scrollPosition = (scrollTop + clientHeight) / scrollHeight;
// Check if we've scrolled past the threshold and conditions are met
const shouldFetch = scrollPosition >= threshold && hasNextPage && !isFetchingNextPage;
if (shouldFetch) {
fetchNextPage();
}
}, throttleMs),
[hasNextPage, isFetchingNextPage, fetchNextPage, threshold, throttleMs],
);
// Set up scroll listener
useEffect(() => {
const element = scrollElementRef.current;
if (!element) return;
// Remove any existing listener first
element.removeEventListener('scroll', handleScroll);
// Add the new listener
element.addEventListener('scroll', handleScroll, { passive: true });
return () => {
element.removeEventListener('scroll', handleScroll);
// Clean up throttled function
handleScroll.cancel?.();
};
}, [handleScroll]);
// Additional effect to re-setup listeners when scroll element changes
useEffect(() => {
const element = scrollElementRef.current;
if (!element) return;
// Remove any existing listener first
element.removeEventListener('scroll', handleScroll);
// Add the new listener
element.addEventListener('scroll', handleScroll, { passive: true });
return () => {
element.removeEventListener('scroll', handleScroll);
// Clean up throttled function
handleScroll.cancel?.();
};
}, [scrollElementRef.current, handleScroll]);
// Function to manually set the scroll container
const setScrollElement = useCallback((element: HTMLElement | null) => {
scrollElementRef.current = element;
}, []);
return {
setScrollElement,
scrollElementRef,
};
};
export default useInfiniteScroll;

View file

@ -0,0 +1,66 @@
import { useCallback, useMemo } from 'react';
interface UseVirtualGridProps {
itemCount: number;
containerWidth: number;
itemHeight: number;
gapSize: number;
mobileColumnsCount: number;
desktopColumnsCount: number;
mobileBreakpoint: number;
}
interface UseVirtualGridReturn {
cardsPerRow: number;
rowCount: number;
rowHeight: number;
getRowItems: (rowIndex: number, items: any[]) => any[];
}
/**
* Custom hook for virtual grid calculations
* Handles responsive grid layout and item positioning for virtualized lists
*/
export const useVirtualGrid = ({
itemCount,
containerWidth,
itemHeight,
gapSize,
mobileColumnsCount,
desktopColumnsCount,
mobileBreakpoint = 768,
}: UseVirtualGridProps): UseVirtualGridReturn => {
// Calculate cards per row based on container width
const cardsPerRow = useMemo(() => {
return containerWidth >= mobileBreakpoint ? desktopColumnsCount : mobileColumnsCount;
}, [containerWidth, mobileBreakpoint, desktopColumnsCount, mobileColumnsCount]);
// Calculate total number of rows needed
const rowCount = useMemo(() => {
return Math.ceil(itemCount / cardsPerRow);
}, [itemCount, cardsPerRow]);
// Calculate row height including gap
const rowHeight = useMemo(() => {
return itemHeight + gapSize;
}, [itemHeight, gapSize]);
// Get items for a specific row
const getRowItems = useCallback(
(rowIndex: number, items: any[]) => {
const startIndex = rowIndex * cardsPerRow;
const endIndex = Math.min(startIndex + cardsPerRow, items.length);
return items.slice(startIndex, endIndex);
},
[cardsPerRow],
);
return {
cardsPerRow,
rowCount,
rowHeight,
getRowItems,
};
};
export default useVirtualGrid;