Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

renterd health updates, stats, directory delete #341

Merged
merged 3 commits into from
Aug 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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/sixty-badgers-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siafoundation/react-renterd': minor
---

Added batch flag to useObjectDelete.
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.
5 changes: 5 additions & 0 deletions .changeset/warm-phones-rush.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Improved the file data size statistic and the detailed breakdown in its tooltip.
5 changes: 5 additions & 0 deletions .changeset/weak-eyes-camp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Fixed an issue where the file health and slab health breakdown was incorrectly reporting everything as 0.
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