This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

update ui for consolidated connection fetching

+146 -41
+2 -2
src/webapp/features/connections/components/addConnectionDrawer/AddConnectionDrawer.tsx
··· 3 3 import { Container, Drawer } from '@mantine/core'; 4 4 import { DEFAULT_OVERLAY_PROPS } from '@/styles/overlays'; 5 5 import AddConnectionForm from './AddConnectionForm'; 6 - import { ConnectionForUrl } from '@semble/types'; 6 + import { ConnectionWithSourceAndTarget } from '@semble/types'; 7 7 8 8 interface Props { 9 9 isOpen: boolean; 10 10 onClose: () => void; 11 11 sourceUrl: string; 12 12 connectionToEdit?: { 13 - connection: ConnectionForUrl['connection']; 13 + connection: ConnectionWithSourceAndTarget['connection']; 14 14 targetUrl: string; 15 15 }; 16 16 }
+2 -2
src/webapp/features/connections/components/addConnectionDrawer/AddConnectionForm.tsx
··· 24 24 import useUpdateConnection from '../../lib/mutations/useUpdateConnection'; 25 25 import { searchUrls } from '../../lib/dal'; 26 26 import { IoMdLink } from 'react-icons/io'; 27 - import { ConnectionForUrl } from '@semble/types'; 27 + import { ConnectionWithSourceAndTarget } from '@semble/types'; 28 28 29 29 interface Props { 30 30 onClose: () => void; 31 31 sourceUrl: string; 32 32 connectionToEdit?: { 33 - connection: ConnectionForUrl['connection']; 33 + connection: ConnectionWithSourceAndTarget['connection']; 34 34 targetUrl: string; 35 35 }; 36 36 }
+2 -1
src/webapp/features/connections/components/connectionFilters/DirectionToggle.tsx
··· 2 2 3 3 import { SegmentedControl } from '@mantine/core'; 4 4 5 - type Direction = 'outgoing' | 'incoming'; 5 + type Direction = 'outgoing' | 'incoming' | 'all'; 6 6 7 7 interface Props { 8 8 value: Direction; ··· 19 19 value={props.value} 20 20 onChange={handleChange} 21 21 data={[ 22 + { label: 'All', value: 'all' }, 22 23 { label: 'Outgoing', value: 'outgoing' }, 23 24 { label: 'Incoming', value: 'incoming' }, 24 25 ]}
+8 -4
src/webapp/features/connections/components/connectionItem/ConnectionItem.tsx
··· 1 - import type { ConnectionForUrl } from '@semble/types'; 1 + import type { ConnectionWithSourceAndTarget } from '@semble/types'; 2 2 import { Stack } from '@mantine/core'; 3 3 import UrlCard from '@/features/cards/components/urlCard/UrlCard'; 4 4 import ConnectionStatus from './ConnectionStatus'; 5 5 6 6 interface Props { 7 - connectionForUrl: ConnectionForUrl; 7 + connection: ConnectionWithSourceAndTarget; 8 8 direction: 'forward' | 'backward'; 9 9 onEdit?: () => void; 10 10 } 11 11 12 12 export default function ConnectionItem(props: Props) { 13 - const urlView = props.connectionForUrl.url; 13 + // For forward connections, show the target; for backward connections, show the source 14 + const urlView = 15 + props.direction === 'forward' 16 + ? props.connection.target 17 + : props.connection.source; 14 18 15 19 return ( 16 20 <Stack gap={'xs'} align="stretch" h={'100%'}> 17 21 <ConnectionStatus 18 - connection={props.connectionForUrl.connection} 22 + connection={props.connection.connection} 19 23 direction={props.direction} 20 24 onEdit={props.onEdit} 21 25 />
+2 -2
src/webapp/features/connections/components/connectionItem/ConnectionStatus.tsx
··· 13 13 Button, 14 14 Box, 15 15 } from '@mantine/core'; 16 - import { ConnectionForUrl, User } from '@semble/types'; 16 + import { ConnectionWithSourceAndTarget, User } from '@semble/types'; 17 17 import Link from 'next/link'; 18 18 import styles from './ConnectionStatus.module.css'; 19 19 import { getRelativeTime } from '@/lib/utils/time'; ··· 26 26 import { notifications } from '@mantine/notifications'; 27 27 28 28 interface Props { 29 - connection: ConnectionForUrl['connection']; 29 + connection: ConnectionWithSourceAndTarget['connection']; 30 30 direction: 'forward' | 'backward'; 31 31 onEdit?: () => void; 32 32 }
+6
src/webapp/features/connections/lib/connectionKeys.ts
··· 30 30 limit, 31 31 connectionTypes, 32 32 ] as const, 33 + allForUrl: (url: string) => ['connections', 'all', url] as const, 34 + allForUrlInfinite: ( 35 + url: string, 36 + limit?: number, 37 + connectionTypes?: ConnectionType[], 38 + ) => ['connections', 'all', url, 'infinite', limit, connectionTypes] as const, 33 39 userConnections: (identifier: string) => 34 40 ['connections', 'user', identifier] as const, 35 41 userConnectionsInfinite: (
+9
src/webapp/features/connections/lib/dal.ts
··· 3 3 import { 4 4 GetForwardConnectionsForUrlParams, 5 5 GetBackwardConnectionsForUrlParams, 6 + GetConnectionsForUrlParams, 6 7 GetConnectionsParams, 7 8 SearchUrlsParams, 8 9 ConnectionType, ··· 41 42 async (params: GetBackwardConnectionsForUrlParams) => { 42 43 const client = createSembleClient(); 43 44 const response = await client.getBackwardConnectionsForUrl(params); 45 + return response; 46 + }, 47 + ); 48 + 49 + export const getConnectionsForUrl = cache( 50 + async (params: GetConnectionsForUrlParams) => { 51 + const client = createSembleClient(); 52 + const response = await client.getConnectionsForUrl(params); 44 53 return response; 45 54 }, 46 55 );
+40
src/webapp/features/connections/lib/queries/useAllConnections.tsx
··· 1 + import { useSuspenseInfiniteQuery } from '@tanstack/react-query'; 2 + import { getConnectionsForUrl } from '../dal'; 3 + import { connectionKeys } from '../connectionKeys'; 4 + import { ConnectionType } from '@semble/types'; 5 + 6 + interface Props { 7 + url: string; 8 + limit?: number; 9 + connectionTypes?: ConnectionType[]; 10 + } 11 + 12 + export default function useAllConnections(props: Props) { 13 + const limit = props?.limit ?? 16; 14 + 15 + const allConnections = useSuspenseInfiniteQuery({ 16 + queryKey: connectionKeys.allForUrlInfinite( 17 + props.url, 18 + props.limit, 19 + props.connectionTypes, 20 + ), 21 + initialPageParam: 1, 22 + queryFn: ({ pageParam = 1 }) => { 23 + return getConnectionsForUrl({ 24 + url: props.url, 25 + direction: 'both', 26 + page: pageParam, 27 + limit, 28 + connectionTypes: props.connectionTypes, 29 + }); 30 + }, 31 + getNextPageParam: (lastPage) => { 32 + if (lastPage.pagination.hasMore) { 33 + return lastPage.pagination.currentPage + 1; 34 + } 35 + return undefined; 36 + }, 37 + }); 38 + 39 + return allConnections; 40 + }
+3 -2
src/webapp/features/connections/lib/queries/useBackwardConnections.tsx
··· 1 1 import { useSuspenseInfiniteQuery } from '@tanstack/react-query'; 2 - import { getBackwardConnectionsForUrl } from '../dal'; 2 + import { getConnectionsForUrl } from '../dal'; 3 3 import { connectionKeys } from '../connectionKeys'; 4 4 import { ConnectionType } from '@semble/types'; 5 5 ··· 20 20 ), 21 21 initialPageParam: 1, 22 22 queryFn: ({ pageParam = 1 }) => { 23 - return getBackwardConnectionsForUrl({ 23 + return getConnectionsForUrl({ 24 24 url: props.url, 25 + direction: 'backward', 25 26 page: pageParam, 26 27 limit, 27 28 connectionTypes: props.connectionTypes,
+3 -2
src/webapp/features/connections/lib/queries/useForwardConnections.tsx
··· 1 1 import { useSuspenseInfiniteQuery } from '@tanstack/react-query'; 2 - import { getForwardConnectionsForUrl } from '../dal'; 2 + import { getConnectionsForUrl } from '../dal'; 3 3 import { connectionKeys } from '../connectionKeys'; 4 4 import { ConnectionType } from '@semble/types'; 5 5 ··· 20 20 ), 21 21 initialPageParam: 1, 22 22 queryFn: ({ pageParam = 1 }) => { 23 - return getForwardConnectionsForUrl({ 23 + return getConnectionsForUrl({ 24 24 url: props.url, 25 + direction: 'forward', 25 26 page: pageParam, 26 27 limit, 27 28 connectionTypes: props.connectionTypes,
+69 -26
src/webapp/features/semble/containers/sembleConnectionsContainer/SembleConnectionsContainer.tsx
··· 2 2 3 3 import useForwardConnections from '@/features/connections/lib/queries/useForwardConnections'; 4 4 import useBackwardConnections from '@/features/connections/lib/queries/useBackwardConnections'; 5 + import useAllConnections from '@/features/connections/lib/queries/useAllConnections'; 5 6 import InfiniteScroll from '@/components/contentDisplay/infiniteScroll/InfiniteScroll'; 6 7 import { Button, Grid, Group, Stack } from '@mantine/core'; 7 8 import SembleConnectionsContainerError from './Error.SembleConnectionsContainer'; ··· 14 15 import { ConnectionFilters } from '@/features/connections/components/connectionFilters/ConnectionFilters'; 15 16 import DirectionToggle from '@/features/connections/components/connectionFilters/DirectionToggle'; 16 17 import { useState } from 'react'; 17 - import { ConnectionType, ConnectionForUrl } from '@semble/types'; 18 + import { ConnectionType, ConnectionWithSourceAndTarget } from '@semble/types'; 18 19 19 - type Direction = 'outgoing' | 'incoming'; 20 + type Direction = 'outgoing' | 'incoming' | 'all'; 20 21 21 22 interface Props { 22 23 url: string; ··· 31 32 null, 32 33 ); 33 34 const [connectionToEdit, setConnectionToEdit] = useState<{ 34 - connection: ConnectionForUrl['connection']; 35 + connection: ConnectionWithSourceAndTarget['connection']; 35 36 targetUrl: string; 36 37 } | null>(null); 37 38 ··· 41 42 }; 42 43 43 44 const handleOpenEditDrawer = ( 44 - connection: ConnectionForUrl['connection'], 45 + connection: ConnectionWithSourceAndTarget['connection'], 45 46 targetUrl: string, 46 47 ) => { 47 48 setConnectionToEdit({ connection, targetUrl }); ··· 79 80 connectionTypes, 80 81 }); 81 82 83 + const { 84 + data: allData, 85 + error: allError, 86 + fetchNextPage: fetchNextAll, 87 + hasNextPage: hasNextAll, 88 + isFetchingNextPage: isFetchingNextAll, 89 + isPending: isPendingAll, 90 + } = useAllConnections({ 91 + url: props.url, 92 + connectionTypes, 93 + }); 94 + 82 95 const allForwardConnections = 83 96 forwardData?.pages.flatMap((page) => page.connections ?? []) ?? []; 84 97 const allBackwardConnections = 85 98 backwardData?.pages.flatMap((page) => page.connections ?? []) ?? []; 99 + const allConnections = 100 + allData?.pages.flatMap((page) => page.connections ?? []) ?? []; 86 101 87 - if (forwardError || backwardError) { 102 + if (forwardError || backwardError || allError) { 88 103 return <SembleConnectionsContainerError />; 89 104 } 90 105 91 106 const connections = 92 - direction === 'outgoing' ? allForwardConnections : allBackwardConnections; 107 + direction === 'outgoing' 108 + ? allForwardConnections 109 + : direction === 'incoming' 110 + ? allBackwardConnections 111 + : allConnections; 93 112 const fetchNextPage = 94 - direction === 'outgoing' ? fetchNextForward : fetchNextBackward; 113 + direction === 'outgoing' 114 + ? fetchNextForward 115 + : direction === 'incoming' 116 + ? fetchNextBackward 117 + : fetchNextAll; 95 118 const hasNextPage = 96 - direction === 'outgoing' ? hasNextForward : hasNextBackward; 119 + direction === 'outgoing' 120 + ? hasNextForward 121 + : direction === 'incoming' 122 + ? hasNextBackward 123 + : hasNextAll; 97 124 const isFetchingNextPage = 98 - direction === 'outgoing' ? isFetchingNextForward : isFetchingNextBackward; 125 + direction === 'outgoing' 126 + ? isFetchingNextForward 127 + : direction === 'incoming' 128 + ? isFetchingNextBackward 129 + : isFetchingNextAll; 99 130 const isPending = 100 - direction === 'outgoing' ? isPendingForward : isPendingBackward; 131 + direction === 'outgoing' 132 + ? isPendingForward 133 + : direction === 'incoming' 134 + ? isPendingBackward 135 + : isPendingAll; 101 136 102 137 return ( 103 138 <> ··· 135 170 loadMore={fetchNextPage} 136 171 > 137 172 <Grid gutter="sm" mx={'auto'} maw={600} w={'100%'}> 138 - {connections.map((connectionForUrl, index) => ( 139 - <Grid.Col key={`${direction}-${index}`} span={12}> 140 - <ConnectionItem 141 - connectionForUrl={connectionForUrl} 142 - direction={ 143 - direction === 'outgoing' ? 'forward' : 'backward' 144 - } 145 - onEdit={() => 146 - handleOpenEditDrawer( 147 - connectionForUrl.connection, 148 - connectionForUrl.url.url, 149 - ) 150 - } 151 - /> 152 - </Grid.Col> 153 - ))} 173 + {connections.map((connection, index) => { 174 + // Determine the actual direction for this specific connection 175 + // If direction is 'all', check if the source URL matches props.url 176 + const isForward = 177 + direction === 'all' 178 + ? connection.source.url === props.url 179 + : direction === 'outgoing'; 180 + const connectionDirection = isForward ? 'forward' : 'backward'; 181 + const targetUrl = isForward 182 + ? connection.target.url 183 + : connection.source.url; 184 + 185 + return ( 186 + <Grid.Col key={`${direction}-${index}`} span={12}> 187 + <ConnectionItem 188 + connection={connection} 189 + direction={connectionDirection} 190 + onEdit={() => { 191 + handleOpenEditDrawer(connection.connection, targetUrl); 192 + }} 193 + /> 194 + </Grid.Col> 195 + ); 196 + })} 154 197 </Grid> 155 198 </InfiniteScroll> 156 199 )}