diff --git a/.changeset/cyan-dots-cover.md b/.changeset/cyan-dots-cover.md new file mode 100644 index 000000000..84fe4a0b4 --- /dev/null +++ b/.changeset/cyan-dots-cover.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/react-renterd': minor +--- + +useObject now includes partialSlab. diff --git a/.changeset/dull-readers-sit.md b/.changeset/dull-readers-sit.md new file mode 100644 index 000000000..bc4f2da89 --- /dev/null +++ b/.changeset/dull-readers-sit.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +File upload and directory creation are now disabled until enough contracts are formed. diff --git a/.changeset/eight-wombats-sneeze.md b/.changeset/eight-wombats-sneeze.md new file mode 100644 index 000000000..330279843 --- /dev/null +++ b/.changeset/eight-wombats-sneeze.md @@ -0,0 +1,5 @@ +--- +'hostd': minor +--- + +Fixed an issue where alert error messages were being cut off. Full error messages are now displayed above all other fields. diff --git a/.changeset/happy-hornets-tickle.md b/.changeset/happy-hornets-tickle.md new file mode 100644 index 000000000..687fe7109 --- /dev/null +++ b/.changeset/happy-hornets-tickle.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +The failed to migrate slab alert now lists the associated objects/files. diff --git a/.changeset/odd-pillows-try.md b/.changeset/odd-pillows-try.md new file mode 100644 index 000000000..dc077238c --- /dev/null +++ b/.changeset/odd-pillows-try.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +New users are now more clearly instructed to configure autopilot and to wait for enough contracts before files can be uploaded. diff --git a/.changeset/plenty-baboons-leave.md b/.changeset/plenty-baboons-leave.md new file mode 100644 index 000000000..99bcb07f0 --- /dev/null +++ b/.changeset/plenty-baboons-leave.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +Node profile information now includes the build version. diff --git a/.changeset/pretty-rules-bake.md b/.changeset/pretty-rules-bake.md new file mode 100644 index 000000000..039f245dd --- /dev/null +++ b/.changeset/pretty-rules-bake.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/react-renterd': minor +--- + +Add useSlabObjects. diff --git a/.changeset/six-mice-work.md b/.changeset/six-mice-work.md new file mode 100644 index 000000000..ef2f6e53a --- /dev/null +++ b/.changeset/six-mice-work.md @@ -0,0 +1,5 @@ +--- +'@siafoundation/react-renterd': minor +--- + +Add useAutopilotState, useBusState, useWorkerState, remove useAutopilotStatus. diff --git a/.changeset/slimy-stingrays-ring.md b/.changeset/slimy-stingrays-ring.md new file mode 100644 index 000000000..c08373205 --- /dev/null +++ b/.changeset/slimy-stingrays-ring.md @@ -0,0 +1,7 @@ +--- +'hostd': minor +'renterd': minor +'walletd': minor +--- + +The connectivity and login check no longer depends on consensus APIs which in some rare cases can be unresponsive. diff --git a/.changeset/smart-scissors-help.md b/.changeset/smart-scissors-help.md new file mode 100644 index 000000000..d217a3c2f --- /dev/null +++ b/.changeset/smart-scissors-help.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +Alerts now show contract additions and removals, formatted address, balance, and more. diff --git a/.changeset/wise-phones-bathe.md b/.changeset/wise-phones-bathe.md new file mode 100644 index 000000000..d396231bc --- /dev/null +++ b/.changeset/wise-phones-bathe.md @@ -0,0 +1,5 @@ +--- +'renterd': minor +--- + +File health tooltip now includes redundancy info and supports partial slabs. diff --git a/apps/hostd/config/routes.ts b/apps/hostd/config/routes.ts index 95b8cd9bc..a9e36f402 100644 --- a/apps/hostd/config/routes.ts +++ b/apps/hostd/config/routes.ts @@ -1,3 +1,5 @@ +import { stateHostKey } from '@siafoundation/react-hostd' + export const routes = { home: '/', volumes: { @@ -20,4 +22,4 @@ export const routes = { login: '/login', } -export const connectivityRoute = '/state/consensus' +export const connectivityRoute = stateHostKey diff --git a/apps/hostd/dialogs/AlertsDialog.tsx b/apps/hostd/dialogs/AlertsDialog.tsx index 14a275250..73c3f5efb 100644 --- a/apps/hostd/dialogs/AlertsDialog.tsx +++ b/apps/hostd/dialogs/AlertsDialog.tsx @@ -13,7 +13,7 @@ import { import { useAlerts, useAlertsDismiss } from '@siafoundation/react-hostd' import { humanDate, humanTime } from '@siafoundation/sia-js' import { cx } from 'class-variance-authority' -import { times } from 'lodash' +import { difference, times } from 'lodash' import { useCallback } from 'react' type Props = { @@ -142,6 +142,11 @@ export function AlertsDialog({ open, onOpenChange }: Props) { + {!!a.data.error && ( + + {a.data.error} + + )}
timestamp @@ -150,7 +155,7 @@ export function AlertsDialog({ open, onOpenChange }: Props) { {humanDate(a.timestamp, { timeStyle: 'medium' })}
- {getOrderedKeys(a.data).map((key) => { + {getOrderedKeys(a.data, skipFields).map((key) => { const value = a.data[key] if (value === undefined) { return null @@ -177,6 +182,8 @@ export function AlertsDialog({ open, onOpenChange }: Props) { ) } +const skipFields = ['error'] + const dataFieldOrder = [ 'contractID', 'blockHeight', @@ -199,8 +206,8 @@ const dataFieldOrder = [ ] // Sort keys by dataFieldOrder, then alphabetically -function getOrderedKeys(obj) { - return Object.keys(obj).sort((a, b) => { +function getOrderedKeys(obj, skip: string[]) { + const keys = Object.keys(obj).sort((a, b) => { const aIndex = dataFieldOrder.indexOf(a) const bIndex = dataFieldOrder.indexOf(b) if (aIndex === -1 && bIndex === -1) { @@ -214,6 +221,7 @@ function getOrderedKeys(obj) { } return aIndex - bIndex }) + return difference(keys, skip) } const dataFields = { diff --git a/apps/renterd/components/CmdRoot/index.tsx b/apps/renterd/components/CmdRoot/index.tsx index 841a077ad..182a10054 100644 --- a/apps/renterd/components/CmdRoot/index.tsx +++ b/apps/renterd/components/CmdRoot/index.tsx @@ -105,7 +105,7 @@ export function CmdRoot({ panel }: Props) { afterSelect() }} /> - {autopilot.state === 'on' && ( + {autopilot.status === 'on' && ( )} diff --git a/apps/renterd/components/Files/Columns/FilesHealthColumn/FilesHealthColumnContents.tsx b/apps/renterd/components/Files/Columns/FilesHealthColumn/FilesHealthColumnContents.tsx index d9610ef6e..48bc84a46 100644 --- a/apps/renterd/components/Files/Columns/FilesHealthColumn/FilesHealthColumnContents.tsx +++ b/apps/renterd/components/Files/Columns/FilesHealthColumn/FilesHealthColumnContents.tsx @@ -66,27 +66,44 @@ export function FilesHealthColumnContents({ 'contractSetShards' ) + const { partialSlab } = obj.data.object + return ( 15 ? 'h-[300px]' : ''} displayHealth={displayHealth} label={label} + minShards={partialSlab ? partialSlab.minShards : slabs[0]?.minShards} + totalShards={ + partialSlab ? partialSlab.totalShards : slabs[0]?.shards.length + } > - {slabs.map((slab) => ( -
- - Slab {slab.key.replace('key:', '').slice(0, 4)}: - - - {slab.contractSetShards}/{slab.shards.length} - -
- ))} + {partialSlab ? ( + + partial slab + + ) : ( + slabs.map((slab) => ( +
+ + Slab {slab.key.replace('key:', '').slice(0, 4)}: + + + {slab.contractSetShards}/{slab.shards.length} + +
+ )) + )}
) } @@ -96,11 +113,15 @@ function Layout({ displayHealth, label, children, + minShards, + totalShards, }: { className?: string children: React.ReactNode displayHealth: number label: string + minShards?: number + totalShards?: number }) { return (
{label} {(displayHealth * 100).toFixed(0)}%
+ {minShards && totalShards ? ( +
+ + redundancy + + + {minShards} of {totalShards} + +
+ ) : null}
diff --git a/apps/renterd/components/Files/EmptyState.tsx b/apps/renterd/components/Files/EmptyState.tsx new file mode 100644 index 000000000..18175ca67 --- /dev/null +++ b/apps/renterd/components/Files/EmptyState.tsx @@ -0,0 +1,79 @@ +import { CloudUpload32, LinkButton, Text } from '@siafoundation/design-system' +import { routes } from '../../config/routes' +import { useFiles } from '../../contexts/files' +import { useAutopilotNotConfigured } from './checks/useAutopilotNotConfigured' +import { useNotEnoughContracts } from './checks/useNotEnoughContracts' +import { StateError } from './StateError' +import { StateNoneMatching } from './StateNoneMatching' +import { StateNoneYet } from './StateNoneYet' + +export function EmptyState() { + const { dataState, activeDirectoryPath } = useFiles() + + const autopilotNotConfigured = useAutopilotNotConfigured() + const notEnoughContracts = useNotEnoughContracts() + + if (dataState === 'noneMatchingFilters') { + return + } + + if (dataState === 'error') { + return + } + + // only show on root directory and when there are no files + if ( + activeDirectoryPath === '/' && + dataState === 'noneYet' && + autopilotNotConfigured.active + ) { + return ( +
+ + + +
+ + Before you can upload files you must configure autopilot. Autopilot + finds contracts with hosts based on the settings you choose. + Autopilot also repairs your data as hosts come and go. + + + Configure autopilot → + +
+
+ ) + } + + // only show on root directory and when there are no files + if ( + activeDirectoryPath === '/' && + dataState === 'noneYet' && + notEnoughContracts.active + ) { + return ( +
+ + + +
+ + There are not enough contracts to upload data yet. Redundancy is + configured to use {notEnoughContracts.required} shards which means + at least that many contracts are required. + + + {notEnoughContracts.count}/{notEnoughContracts.required} + +
+
+ ) + } + + if (dataState === 'noneYet') { + return + } + + return null +} diff --git a/apps/renterd/components/Files/FilesActionsMenu.tsx b/apps/renterd/components/Files/FilesActionsMenu.tsx index aeab2e015..8694f8482 100644 --- a/apps/renterd/components/Files/FilesActionsMenu.tsx +++ b/apps/renterd/components/Files/FilesActionsMenu.tsx @@ -8,13 +8,17 @@ import { useFiles } from '../../contexts/files' import { useDropzone } from 'react-dropzone' import { FilesViewDropdownMenu } from './FilesViewDropdownMenu' import { useDialog } from '../../contexts/dialog' +import { useCanUpload } from './useCanUpload' export function FilesActionsMenu() { const { openDialog } = useDialog() const { uploadFiles } = useFiles() + const canUpload = useCanUpload() + const { getRootProps, getInputProps } = useDropzone({ noDrag: true, + noClick: !canUpload, onDrop: uploadFiles, }) @@ -23,11 +27,12 @@ export function FilesActionsMenu() { -