Skip to content

Commit

Permalink
feat: renterd health updates
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Aug 8, 2023
1 parent d1654b5 commit 79147c3
Show file tree
Hide file tree
Showing 28 changed files with 908 additions and 616 deletions.
5 changes: 5 additions & 0 deletions .changeset/chatty-poets-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'website': minor
---

get-started and other legacy pages now redirect to the root path.
5 changes: 5 additions & 0 deletions .changeset/empty-apes-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

The files health feature has been refined to be more accurate and clear and now includes a global health value in the stats bar.
5 changes: 5 additions & 0 deletions .changeset/ninety-spiders-glow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Entire directories can now be deleted from the directory context menu.
5 changes: 5 additions & 0 deletions .changeset/perfect-boats-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

The files explorer no longer makes a metadata request for every file in the list.
5 changes: 5 additions & 0 deletions .changeset/tall-mirrors-leave.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

File health is now based on the new health values returned by the API.
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import {
LoadingDots,
ScrollArea,
Separator,
Text,
} from '@siafoundation/design-system'
import { useObject } from '@siafoundation/react-renterd'
import { cx } from 'class-variance-authority'
import { sortBy } from 'lodash'
import { computeSlabContractSetShards } from '../../../../contexts/files/health'
import { ObjectData } from '../../../../contexts/files/types'
import { useHealthLabel } from '../../../../hooks/useHealthLabel'

export function FilesHealthColumnContents({
path,
isUploading,
isDirectory,
health: _health,
size,
}: ObjectData) {
const obj = useObject({
disabled: isUploading || isDirectory,
params: {
key: path.slice(1),
},
config: {
swr: {
dedupingInterval: 5000,
},
},
})

const { displayHealth, label } = useHealthLabel({
health: _health,
size,
isDirectory,
})

if (obj.isValidating) {
return (
<Layout displayHealth={displayHealth} label={label}>
<div className="flex justify-center my-2">
<LoadingDots />
</div>
</Layout>
)
}

if (!obj.data?.object) {
return (
<Layout displayHealth={displayHealth} label={label}>
<Text size="12">Error fetching slab metadata.</Text>
</Layout>
)
}

const slabs = sortBy(
obj.data.object.slabs.map((s) => ({
...s.slab,
contractSetShards: computeSlabContractSetShards({
totalShards: s.slab.shards.length,
minShards: s.slab.minShards,
health: s.slab.health,
}),
})),
'contractSetShards'
)

return (
<Layout
className={slabs.length > 15 ? 'h-[300px]' : ''}
displayHealth={displayHealth}
label={label}
>
{slabs.map((slab) => (
<div key={slab.key} className="flex justify-between gap-2">
<Text
size="12"
color="subtle"
className="flex items-center"
font="mono"
>
Slab {slab.key.replace('key:', '').slice(0, 4)}:
</Text>
<Text size="12" className="flex items-center">
{slab.contractSetShards}/{slab.shards.length}
</Text>
</div>
))}
</Layout>
)
}

function Layout({
className,
displayHealth,
label,
children,
}: {
className?: string
children: React.ReactNode
displayHealth: number
label: string
}) {
return (
<div
className={cx('z-10 flex flex-col pb-1 -mx-1 overflow-hidden', className)}
>
<div className="flex justify-between gap-2 pt-0.5 pb-px px-2">
<Text size="12">{label}</Text>
<Text size="12">{(displayHealth * 100).toFixed(0)}%</Text>
</div>
<div className="px-2">
<Separator className="w-full my-1" />
</div>
<div className="flex-1 overflow-hidden">
<ScrollArea>
<div className="px-2">{children}</div>
</ScrollArea>
</div>
</div>
)
}
59 changes: 59 additions & 0 deletions apps/renterd/components/Files/Columns/FilesHealthColumn/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import { HoverCard, LoadingDots, Text } from '@siafoundation/design-system'
import { ObjectData } from '../../../../contexts/files/types'
import { useHealthLabel } from '../../../../hooks/useHealthLabel'
import { FilesHealthColumnContents } from './FilesHealthColumnContents'

export function FilesHealthColumn(props: ObjectData) {
const { name, isUploading, isDirectory, health: _health, size } = props
const { displayHealth, label, color, icon } = useHealthLabel({
health: _health,
size,
isDirectory,
})

if (isDirectory) {
if (name === '..') {
return null
}
return (
<HoverCard
rootProps={{
openDelay: 100,
}}
trigger={
<Text color={color} className="flex cursor-pointer">
{icon}
</Text>
}
>
<div className="z-10 flex flex-col -mx-1 overflow-hidden">
<div className="flex justify-between gap-2 py-0.5 px-2">
<Text size="12">{label}</Text>
<Text size="12">{(displayHealth * 100).toFixed(0)}%</Text>
</div>
</div>
</HoverCard>
)
}

if (isUploading) {
return <LoadingDots />
}

return (
<HoverCard
rootProps={{
openDelay: 100,
}}
trigger={
<Text color={color} className="flex cursor-pointer">
{icon}
</Text>
}
>
{/* important to separate contents so that each row does not trigger 1+n
fetching */}
<FilesHealthColumnContents {...props} />
</HoverCard>
)
}
42 changes: 42 additions & 0 deletions apps/renterd/components/Files/DirectoryContextMenu.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {
DropdownMenu,
DropdownMenuItem,
Button,
DropdownMenuLeftSlot,
Delete16,
DropdownMenuLabel,
FolderIcon,
} from '@siafoundation/design-system'
import { useDirectoryDelete } from './useDirectoryDelete'

type Props = {
path: string
size: number
}

export function DirectoryContextMenu({ path, size }: Props) {
const directoryConfirmDelete = useDirectoryDelete()

return (
<DropdownMenu
trigger={
<Button variant="ghost" icon="hover">
<FolderIcon size={16} />
</Button>
}
contentProps={{ align: 'start' }}
>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onSelect={() => {
directoryConfirmDelete(path, size)
}}
>
<DropdownMenuLeftSlot>
<Delete16 />
</DropdownMenuLeftSlot>
Delete directory
</DropdownMenuItem>
</DropdownMenu>
)
}
65 changes: 0 additions & 65 deletions apps/renterd/components/Files/DirectoryDropdownMenu.tsx

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import {
DropdownMenuItem,
copyToClipboard,
DropdownMenuLeftSlot,
Copy16,
} from '@siafoundation/design-system'
import { useObject } from '@siafoundation/react-renterd'

type Props = {
path: string
}

// Separating out avoids fetching n objects metadata and only fetches the
// specific one when the user triggers the context menu.
export function CopyMetadataMenuItem({ path }: Props) {
const obj = useObject({
params: {
key: path.slice(1),
},
config: {
swr: {
dedupingInterval: 5000,
},
},
})

return (
<DropdownMenuItem
disabled={!obj.data}
onSelect={() => {
if (obj.data) {
copyToClipboard(
JSON.stringify(obj.data.object, null, 2),
'object metadata'
)
}
}}
>
<DropdownMenuLeftSlot>
<Copy16 />
</DropdownMenuLeftSlot>
Copy metadata
</DropdownMenuItem>
)
}
Loading

0 comments on commit 79147c3

Please sign in to comment.