From a88f48751f98e3675bb630070398b12be83b49b7 Mon Sep 17 00:00:00 2001 From: florian <> Date: Wed, 27 Mar 2024 14:02:41 +0100 Subject: [PATCH] feat: Added distribution info --- src/components/Layout/Layout.css | 2 +- src/components/ServerList/Server.tsx | 94 ++++++++++++++++++++++++ src/components/ServerList/ServerList.css | 3 +- src/components/ServerList/ServerList.tsx | 77 +++++-------------- src/pages/Home.tsx | 26 +------ src/pages/Transfer.tsx | 2 +- src/utils/useServerInfo.ts | 27 ++++++- src/utils/useServers.ts | 2 +- 8 files changed, 146 insertions(+), 87 deletions(-) create mode 100644 src/components/ServerList/Server.tsx diff --git a/src/components/Layout/Layout.css b/src/components/Layout/Layout.css index ccb40df..6ba27ef 100644 --- a/src/components/Layout/Layout.css +++ b/src/components/Layout/Layout.css @@ -3,7 +3,7 @@ } .content { - @apply flex flex-col self-center sm:w-4/6 w-full; + @apply flex flex-col self-center sm:w-10/12 lg:w-4/6 w-full; } .title { diff --git a/src/components/ServerList/Server.tsx b/src/components/ServerList/Server.tsx new file mode 100644 index 0000000..e916109 --- /dev/null +++ b/src/components/ServerList/Server.tsx @@ -0,0 +1,94 @@ +import { + ArrowPathIcon, + ArrowUpOnSquareStackIcon, + CheckBadgeIcon, + ClockIcon, + CubeIcon, + DocumentDuplicateIcon, + ExclamationCircleIcon, + ExclamationTriangleIcon, + ServerIcon, + XMarkIcon, +} from '@heroicons/react/24/outline'; +import { Server } from '../../utils/useServers'; +import { ServerInfo } from '../../utils/useServerInfo'; +import { formatDate, formatFileSize } from '../../utils'; + +type ServerProps = { + server: Server; + serverInfo: ServerInfo; + selectedServer?: string | undefined; + setSelectedServer?: React.Dispatch>; + onTransfer?: (server: string) => void; + onCancel?: () => void; + blobsOnlyOnThisServer: number; +}; + +const Server = ({ + server, + selectedServer, + setSelectedServer, + serverInfo, + onTransfer, + onCancel, + blobsOnlyOnThisServer, +}: ServerProps) => { + return ( +
setSelectedServer && setSelectedServer(server.name)} + > +
+ +
+
+
+ {server.name} + {serverInfo.isLoading && } +
+
+
+ {serverInfo.count} +
+
+ {formatFileSize(serverInfo.size)} +
+
+ {formatDate(serverInfo.lastChange)} +
+
+ {blobsOnlyOnThisServer > 0 ? ( +
+ {blobsOnlyOnThisServer} objects only available here +
+ ) : ( +
+ all objects distributed. +
+ )} +
+
+
+ {((selectedServer == server.name && onTransfer) || onCancel) && ( +
+ {selectedServer == server.name && onTransfer && ( + onTransfer(server.name)}> + Transfer + + )} + {onCancel && ( + onCancel()}> + + + )} +
+ )} +
+ ); +}; + +export default Server; diff --git a/src/components/ServerList/ServerList.css b/src/components/ServerList/ServerList.css index 648c9fa..221f9d2 100644 --- a/src/components/ServerList/ServerList.css +++ b/src/components/ServerList/ServerList.css @@ -15,7 +15,8 @@ } .server-stats { - @apply flex flex-row gap-8; + @apply grid grid-cols-4 gap-8; + grid-template-columns: 4em 6em 8em auto; } .server-stat svg { diff --git a/src/components/ServerList/ServerList.tsx b/src/components/ServerList/ServerList.tsx index 7139234..d8feaf6 100644 --- a/src/components/ServerList/ServerList.tsx +++ b/src/components/ServerList/ServerList.tsx @@ -1,19 +1,10 @@ -import { - ArrowPathIcon, - ArrowUpOnSquareStackIcon, - ClockIcon, - CubeIcon, - DocumentDuplicateIcon, - ServerIcon, - XMarkIcon, -} from '@heroicons/react/24/outline'; -import { formatDate, formatFileSize } from '../../utils'; import { useServerInfo } from '../../utils/useServerInfo'; +import { Server as ServerType } from '../../utils/useServers'; +import Server from './Server'; import './ServerList.css'; -import { Server } from '../../utils/useServers'; type ServerListProps = { - servers: Server[]; + servers: ServerType[]; selectedServer?: string | undefined; setSelectedServer?: React.Dispatch>; onTransfer?: (server: string) => void; @@ -21,54 +12,24 @@ type ServerListProps = { }; export const ServerList = ({ servers, selectedServer, setSelectedServer, onTransfer, onCancel }: ServerListProps) => { - const serverInfo = useServerInfo(); - // + const { serverInfo, distribution } = useServerInfo(); + const blobsWithOnlyOneOccurance = Object.values(distribution) + .filter(d => d.servers.length == 1) + .map(d => ({ ...d.blob, server: d.servers[0] })); + return (
- {servers.map((server, sx) => ( -
setSelectedServer && setSelectedServer(server.name)} - > -
- -
-
-
- {server.name} - {serverInfo[server.name].isLoading && } -
-
-
- {serverInfo[server.name].count} -
-
- {formatFileSize(serverInfo[server.name].size)} -
-
- {formatDate(serverInfo[server.name].lastChange)} -
-
-
- {((selectedServer == server.name && onTransfer) || onCancel) && ( -
- {selectedServer == server.name && onTransfer && ( - onTransfer(server.name)}> - Transfer - - )} - {onCancel && ( - onCancel()}> - - - )} -
- )} -
+ {servers.map(server => ( + b.server == server.name).length} + > ))}
); diff --git a/src/pages/Home.tsx b/src/pages/Home.tsx index 43bcdec..4376e18 100644 --- a/src/pages/Home.tsx +++ b/src/pages/Home.tsx @@ -24,35 +24,13 @@ import { useNavigate } from 'react-router-dom'; function Home() { const { loginWithExtension, signEventTemplate } = useNDK(); const [selectedServer, setSelectedServer] = useState(); - const serverInfo = useServerInfo(); + const { serverInfo } = useServerInfo(); const navigate = useNavigate(); useEffect(() => { loginWithExtension(); }, []); - /*, - combine: (results) => { - const dict: BlobDictionary = {}; - - results.forEach((server) => - server.data && server.data.forEach((blob: BlobDescriptor) => { - if (dict[blob.sha256]) { - dict[blob.sha256].urls.push(blob.url); - } else { - dict[blob.sha256] = { - ...blob, - urls: [blob.url], - }; - } - }) - ); - - return { - data: dict, - }; - },*/ - const queryClient = useQueryClient(); const deleteBlob = useMutation({ @@ -64,7 +42,7 @@ function Home() { queryClient.setQueryData(['blobs', variables.serverName], (oldData: BlobDescriptor[]) => oldData ? oldData.filter(b => b.sha256 !== variables.hash) : oldData ); - console.log({ key: ['blobs', variables.serverName] }); + // console.log({ key: ['blobs', variables.serverName] }); }, }); diff --git a/src/pages/Transfer.tsx b/src/pages/Transfer.tsx index 55abc6f..d3e955c 100644 --- a/src/pages/Transfer.tsx +++ b/src/pages/Transfer.tsx @@ -28,7 +28,7 @@ type TransferStatus = { export const Transfer = () => { const { source: transferSource } = useParams(); const navigate = useNavigate(); - const serverInfo = useServerInfo(); + const {serverInfo} = useServerInfo(); const [transferTarget, setTransferTarget] = useState(); const { signEventTemplate } = useNDK(); const queryClient = useQueryClient(); diff --git a/src/utils/useServerInfo.ts b/src/utils/useServerInfo.ts index 52ea656..d1186f1 100644 --- a/src/utils/useServerInfo.ts +++ b/src/utils/useServerInfo.ts @@ -15,6 +15,10 @@ export type ServerInfo = { blobs?: BlobDescriptor[]; }; +type BlobDictionary = { + [key: string]: { blob: BlobDescriptor; servers: string[] }; +}; + export const useServerInfo = () => { const servers = useServers(); const { user, signEventTemplate } = useNDK(); @@ -58,5 +62,26 @@ export const useServerInfo = () => { return info; }, [servers, blobs]); - return serverInfo; + const distribution = useMemo(() => { + const dict: BlobDictionary = {}; + + servers.forEach(server => { + const si = serverInfo[server.name]; + + si.blobs && + si.blobs.forEach((blob: BlobDescriptor) => { + if (dict[blob.sha256]) { + dict[blob.sha256].servers.push(server.name); + } else { + dict[blob.sha256] = { + blob, + servers: [server.name], + }; + } + }); + }); + return dict; + }, [servers, serverInfo]); + + return {serverInfo, distribution}; }; diff --git a/src/utils/useServers.ts b/src/utils/useServers.ts index 9ded52d..6aa7fde 100644 --- a/src/utils/useServers.ts +++ b/src/utils/useServers.ts @@ -22,7 +22,7 @@ export const useServers = (): Server[] => { const pubkey = user?.npub && (nip19.decode(user?.npub).data as string); // TODO validate type const serverListEvent = useEvent({ kinds: [10063 as NDKKind], authors: [pubkey!] }, { disable: !pubkey }); - console.log(serverListEvent); + const servers = useMemo(() => { const serverUrls = uniqAndSort( [...(serverListEvent?.getMatchingTags('r').map(t => t[1]) || []), ...additionalServers].map(s =>