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

feat: renterd alert improvements and reset account drift #538

Merged
merged 1 commit into from Mar 25, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/dull-birds-compare.md
@@ -0,0 +1,5 @@
---
'@siafoundation/react-renterd': minor
---

Added useAccountResetDrift.
5 changes: 5 additions & 0 deletions .changeset/fuzzy-brooms-poke.md
@@ -0,0 +1,5 @@
---
'renterd': patch
---

Fixed an issue where the alerts list would trigger an excessive number of API calls to fetch contract and host metadata.
5 changes: 5 additions & 0 deletions .changeset/khaki-pots-deny.md
@@ -0,0 +1,5 @@
---
'@siafoundation/design-system': minor
---

Table now has row specific cell class name props that do not apply to the table header.
5 changes: 5 additions & 0 deletions .changeset/nine-wolves-build.md
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Account alerts now feature an accounts context menu with the option to reset account drift. Closes https://github.com/SiaFoundation/web/issues/524
7 changes: 7 additions & 0 deletions .changeset/ninety-donkeys-turn.md
@@ -0,0 +1,7 @@
---
'hostd': minor
'renterd': minor
'walletd': minor
---

Context menus now all use a caret icon.
5 changes: 5 additions & 0 deletions .changeset/purple-moose-wink.md
@@ -0,0 +1,5 @@
---
'renterd': minor
---

The contract set change alert data fields are now displayed as one field that shows additions and removals for each contract in one timeline.
5 changes: 5 additions & 0 deletions .changeset/wicked-mirrors-smell.md
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Alert table row cell content is now aligned to the top of each row.
4 changes: 2 additions & 2 deletions apps/hostd/components/Contracts/ContractContextMenu.tsx
Expand Up @@ -11,7 +11,7 @@ import {
Tooltip,
Text,
} from '@siafoundation/design-system'
import { Draggable16, DataCheck16 } from '@siafoundation/react-icons'
import { CaretDown16, DataCheck16 } from '@siafoundation/react-icons'
import {
ContractStatus,
useContractsIntegrityCheck,
Expand Down Expand Up @@ -62,7 +62,7 @@ export function ContractContextMenu({
<DropdownMenu
trigger={
<Button variant="ghost" icon="hover" {...buttonProps}>
<Draggable16 />
<CaretDown16 />
</Button>
}
contentProps={{ align: 'start', ...contentProps }}
Expand Down
4 changes: 2 additions & 2 deletions apps/hostd/components/Volumes/VolumeContextMenu.tsx
Expand Up @@ -10,7 +10,7 @@ import {
truncate,
} from '@siafoundation/design-system'
import {
Draggable16,
CaretDown16,
Ruler16,
Delete16,
Locked16,
Expand Down Expand Up @@ -47,7 +47,7 @@ export function VolumeContextMenu({ id, contentProps, buttonProps }: Props) {
<DropdownMenu
trigger={
<Button variant="ghost" icon="hover" {...buttonProps}>
<Draggable16 />
<CaretDown16 />
</Button>
}
contentProps={{ align: 'start', ...contentProps }}
Expand Down
73 changes: 73 additions & 0 deletions apps/renterd/components/AccountContextMenu.tsx
@@ -0,0 +1,73 @@
import {
DropdownMenu,
DropdownMenuItem,
Button,
DropdownMenuLeftSlot,
DropdownMenuLabel,
Text,
copyToClipboard,
} from '@siafoundation/design-system'
import { Copy16, ResetAlt16, CaretDown16 } from '@siafoundation/react-icons'
import { useAccountResetDrift } from '@siafoundation/react-renterd'

type Props = {
id: string
contentProps?: React.ComponentProps<typeof DropdownMenu>['contentProps']
buttonProps?: React.ComponentProps<typeof Button>
trigger?: React.ReactNode
}

export function AccountContextMenu({
id,
contentProps,
buttonProps,
trigger,
}: Props) {
const resetDrift = useAccountResetDrift()
return (
<DropdownMenu
trigger={
trigger || (
<Button icon="hover" variant="ghost" {...buttonProps}>
<CaretDown16 />
</Button>
)
}
contentProps={{
align: 'start',
...contentProps,
onClick: (e) => {
e.stopPropagation()
},
}}
>
<div className="px-1.5 py-1">
<Text size="14" weight="medium" color="subtle">
Account {id.slice(0, 20)}...
</Text>
</div>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuItem
onSelect={() =>
resetDrift.post({
params: {
id,
},
})
}
>
<DropdownMenuLeftSlot>
<ResetAlt16 />
</DropdownMenuLeftSlot>
Reset account drift
</DropdownMenuItem>
<DropdownMenuLabel>Copy</DropdownMenuLabel>
<DropdownMenuItem onSelect={() => copyToClipboard(id, 'account ID')}>
<DropdownMenuLeftSlot>
<Copy16 />
</DropdownMenuLeftSlot>
Account ID
</DropdownMenuItem>
</DropdownMenu>
)
}
4 changes: 2 additions & 2 deletions apps/renterd/components/Alerts/AlertContextMenu.tsx
Expand Up @@ -6,7 +6,7 @@ import {
DropdownMenuLabel,
Text,
} from '@siafoundation/design-system'
import { Draggable16, Checkmark16 } from '@siafoundation/react-icons'
import { CaretDown16, Checkmark16 } from '@siafoundation/react-icons'
import { useAlerts } from '../../contexts/alerts'

type Props = {
Expand All @@ -22,7 +22,7 @@ export function AlertContextMenu({ id, contentProps, buttonProps }: Props) {
<DropdownMenu
trigger={
<Button variant="ghost" icon="hover" {...buttonProps}>
<Draggable16 />
<CaretDown16 />
</Button>
}
contentProps={{
Expand Down
97 changes: 67 additions & 30 deletions apps/renterd/components/Contracts/ContractContextMenu.tsx
Expand Up @@ -8,7 +8,7 @@ import {
copyToClipboard,
} from '@siafoundation/design-system'
import {
Draggable16,
CaretDown16,
ListChecked16,
Filter16,
Copy16,
Expand All @@ -31,36 +31,26 @@ import { useContractConfirmDelete } from './useContractConfirmDelete'
type Props = {
id: string
trigger?: React.ReactNode
address: string
publicKey: string
hostAddress: string
hostKey: string
contentProps?: React.ComponentProps<typeof DropdownMenu>['contentProps']
buttonProps?: React.ComponentProps<typeof Button>
}

export function ContractContextMenu({
id,
trigger,
address,
publicKey,
hostAddress,
hostKey,
contentProps,
buttonProps,
}: Props) {
const router = useRouter()
const { setFilter: setHostsFilter, resetFilters: resetHostsFilters } =
useHosts()
const { setFilter: setContractsFilter, resetFilters: resetContractsFilters } =
useContracts()
const blocklist = useHostsBlocklist()
const allowlist = useHostsAllowlist()
const blocklistUpdate = useBlocklistUpdate()
const allowlistUpdate = useAllowlistUpdate()
const contractConfirmDelete = useContractConfirmDelete()
return (
<DropdownMenu
trigger={
trigger || (
<Button variant="ghost" icon="hover" {...buttonProps}>
<Draggable16 />
<CaretDown16 />
</Button>
)
}
Expand All @@ -72,19 +62,50 @@ export function ContractContextMenu({
},
}}
>
<ContractContextMenuContent
id={id}
hostAddress={hostAddress}
hostKey={hostKey}
/>
</DropdownMenu>
)
}

export function ContractContextMenuContent({
id,
hostAddress,
hostKey,
}: {
id: string
hostAddress?: string
hostKey?: string
}) {
const router = useRouter()
const { setFilter: setHostsFilter, resetFilters: resetHostsFilters } =
useHosts()
const { setFilter: setContractsFilter, resetFilters: resetContractsFilters } =
useContracts()
const blocklist = useHostsBlocklist()
const allowlist = useHostsAllowlist()
const blocklistUpdate = useBlocklistUpdate()
const allowlistUpdate = useAllowlistUpdate()
const contractConfirmDelete = useContractConfirmDelete()
return (
<>
<div className="px-1.5 py-1">
<Text size="14" weight="medium" color="subtle">
Contract {publicKey.slice(0, 24)}...
Contract {id.slice(0, 24)}...
</Text>
</div>
<DropdownMenuLabel>Filters</DropdownMenuLabel>
<DropdownMenuItem
disabled={!hostAddress}
onSelect={() => {
resetHostsFilters()
setHostsFilter({
id: 'addressContains',
value: address,
label: `Address contains ${address}`,
value: hostAddress,
label: `Address contains ${hostAddress}`,
})
router.push(routes.hosts.index)
}}
Expand All @@ -95,9 +116,10 @@ export function ContractContextMenu({
Filter hosts by host address
</DropdownMenuItem>
<DropdownMenuItem
disabled={!hostAddress}
onSelect={() => {
resetContractsFilters()
setContractsFilter(addressContainsFilter(address))
setContractsFilter(addressContainsFilter(hostAddress))
router.push(routes.contracts.index)
}}
>
Expand All @@ -107,9 +129,10 @@ export function ContractContextMenu({
Filter contracts by host address
</DropdownMenuItem>
<DropdownMenuItem
disabled={!hostKey}
onSelect={() => {
resetContractsFilters()
setContractsFilter(publicKeyContainsFilter(publicKey))
setContractsFilter(publicKeyContainsFilter(hostKey))
router.push(routes.contracts.index)
}}
>
Expand All @@ -119,30 +142,42 @@ export function ContractContextMenu({
Filter contracts by host public key
</DropdownMenuItem>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
{blocklist.data?.find((l) => l === address) ? (
<DropdownMenuItem onSelect={() => blocklistUpdate([], [address])}>
{blocklist.data?.find((l) => l === hostAddress) ? (
<DropdownMenuItem
disabled={!hostAddress}
onSelect={() => blocklistUpdate([], [hostAddress])}
>
<DropdownMenuLeftSlot>
<ListChecked16 />
</DropdownMenuLeftSlot>
Remove host address from blocklist
</DropdownMenuItem>
) : (
<DropdownMenuItem onSelect={() => blocklistUpdate([address], [])}>
<DropdownMenuItem
disabled={!hostAddress}
onSelect={() => blocklistUpdate([hostAddress], [])}
>
<DropdownMenuLeftSlot>
<ListChecked16 />
</DropdownMenuLeftSlot>
Add host address to blocklist
</DropdownMenuItem>
)}
{allowlist.data?.find((l) => l === publicKey) ? (
<DropdownMenuItem onSelect={() => allowlistUpdate([], [publicKey])}>
{allowlist.data?.find((l) => l === hostKey) ? (
<DropdownMenuItem
disabled={!hostKey}
onSelect={() => allowlistUpdate([], [hostKey])}
>
<DropdownMenuLeftSlot>
<ListChecked16 />
</DropdownMenuLeftSlot>
Remove host public key from allowlist
</DropdownMenuItem>
) : (
<DropdownMenuItem onSelect={() => allowlistUpdate([publicKey], [])}>
<DropdownMenuItem
disabled={!hostKey}
onSelect={() => allowlistUpdate([hostKey], [])}
>
<DropdownMenuLeftSlot>
<ListChecked16 />
</DropdownMenuLeftSlot>
Expand All @@ -163,21 +198,23 @@ export function ContractContextMenu({
Contract ID
</DropdownMenuItem>
<DropdownMenuItem
onSelect={() => copyToClipboard(publicKey, 'host public key')}
disabled={!hostKey}
onSelect={() => copyToClipboard(hostKey, 'host public key')}
>
<DropdownMenuLeftSlot>
<Copy16 />
</DropdownMenuLeftSlot>
Host public key
</DropdownMenuItem>
<DropdownMenuItem
onSelect={() => copyToClipboard(address, 'host address')}
disabled={!hostAddress}
onSelect={() => copyToClipboard(hostAddress, 'host address')}
>
<DropdownMenuLeftSlot>
<Copy16 />
</DropdownMenuLeftSlot>
Host address
</DropdownMenuItem>
</DropdownMenu>
</>
)
}