Skip to content

Commit

Permalink
feat: renterd file sorting
Browse files Browse the repository at this point in the history
  • Loading branch information
alexfreska committed Nov 29, 2023
1 parent 5733911 commit 0cb370d
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 75 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-drinks-work.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'renterd': minor
---

Files can now be sorted by name and health, ascending or descending.
5 changes: 5 additions & 0 deletions .changeset/rude-ways-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@siafoundation/react-renterd': minor
---

useObjectDirectory now supports sortBy and sortDir.
18 changes: 15 additions & 3 deletions apps/renterd/contexts/files/dataset.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useBuckets, useObjectDirectory } from '@siafoundation/react-renterd'
import { sortBy, toPairs } from 'lodash'
import useSWR from 'swr'
import { useContracts } from '../contracts'
import { ObjectData } from './types'
import { ObjectData, SortField } from './types'
import {
bucketAndKeyParamsFromPath,
bucketAndResponseKeyToFilePath,
Expand All @@ -18,11 +18,18 @@ import { useRouter } from 'next/router'
type Props = {
activeDirectoryPath: string
uploadsList: ObjectData[]
sortDirection: 'asc' | 'desc'
sortField: SortField
}

const defaultLimit = 50

export function useDataset({ activeDirectoryPath, uploadsList }: Props) {
export function useDataset({
activeDirectoryPath,
uploadsList,
sortDirection,
sortField,
}: Props) {
const buckets = useBuckets()

const router = useRouter()
Expand All @@ -34,6 +41,8 @@ export function useDataset({ activeDirectoryPath, uploadsList }: Props) {
disabled: !activeBucketName,
params: {
...bucketAndKeyParamsFromPath(activeDirectoryPath),
sortBy: sortField,
sortDir: sortDirection,
offset,
limit,
},
Expand Down Expand Up @@ -96,8 +105,11 @@ export function useDataset({ activeDirectoryPath, uploadsList }: Props) {
}
const all = sortBy(
toPairs(dataMap).map((p) => p[1]),
'path'
sortField as keyof ObjectData
)
if (sortDirection === 'desc') {
all.reverse()
}
return all
},
{
Expand Down
75 changes: 30 additions & 45 deletions apps/renterd/contexts/files/index.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,40 @@
import {
useClientFilteredDataset,
useClientFilters,
useDatasetEmptyState,
useServerFilters,
useTableState,
} from '@siafoundation/design-system'
import { useRouter } from 'next/router'
import { createContext, useCallback, useContext, useMemo } from 'react'
import { columns } from './columns'
import {
defaultSortField,
columnsDefaultVisible,
ObjectData,
sortOptions,
} from './types'
import { defaultSortField, columnsDefaultVisible, sortOptions } from './types'
import { FullPath, FullPathSegments, pathSegmentsToPath } from './paths'
import { useUploads } from './uploads'
import { useDownloads } from './downloads'
import { useDataset } from './dataset'

function useFilesMain() {
const {
configurableColumns,
enabledColumns,
sortableColumns,
toggleColumnVisibility,
setColumnsVisible,
setColumnsHidden,
toggleSort,
setSortDirection,
setSortField,
sortField,
sortDirection,
resetDefaultColumnVisibility,
} = useTableState('renterd/v0/objects', {
columns,
columnsDefaultVisible,
sortOptions,
defaultSortField,
})
const router = useRouter()
const { filters, setFilter, removeFilter, removeLastFilter, resetFilters } =
useServerFilters()

// [bucket, key, directory]
const activeDirectory = useMemo<FullPathSegments>(
Expand Down Expand Up @@ -57,59 +72,30 @@ function useFilesMain() {
const { limit, offset, response, dataset } = useDataset({
activeDirectoryPath,
uploadsList,
})

const {
configurableColumns,
enabledColumns,
sortableColumns,
toggleColumnVisibility,
setColumnsVisible,
setColumnsHidden,
toggleSort,
setSortDirection,
setSortField,
sortField,
sortDirection,
resetDefaultColumnVisibility,
} = useTableState('renterd/v0/objects', {
columns,
columnsDefaultVisible,
sortOptions,
defaultSortField,
})

const { filters, setFilter, removeFilter, removeLastFilter, resetFilters } =
useClientFilters<ObjectData>()

const datasetFiltered = useClientFilteredDataset({
dataset,
filters,
sortField,
sortDirection,
})

const pageCount = datasetFiltered?.length || 0
const datasetPage = useMemo(() => {
if (!datasetFiltered) {
if (!dataset) {
return null
}
if (activeDirectory.length > 0 && datasetFiltered.length > 0) {
if (activeDirectory.length > 0 && dataset.length > 0) {
return [
{
id: '..',
name: '..',
path: '..',
type: 'directory',
},
...datasetFiltered,
...dataset,
]
}
return datasetFiltered
return dataset
// Purposely do not include activeDirectory - we only want to update
// when new data fetching is complete.
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [datasetFiltered])
}, [dataset])

const filteredTableColumns = useMemo(
() =>
Expand All @@ -120,7 +106,7 @@ function useFilesMain() {
)

const dataState = useDatasetEmptyState(
datasetFiltered,
dataset,
response.isValidating,
response.error,
filters
Expand All @@ -142,8 +128,7 @@ function useFilesMain() {
limit,
offset,
datasetPage,
pageCount,
datasetCount: datasetFiltered?.length || 0,
pageCount: dataset?.length || 0,
columns: filteredTableColumns,
uploadFiles,
uploadsList,
Expand Down
7 changes: 6 additions & 1 deletion apps/renterd/contexts/files/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export const columnsDefaultVisible: TableColumnId[] = [
'health',
]

export type SortField = 'name'
export type SortField = 'name' | 'health'

export const defaultSortField: SortField = 'name'

Expand All @@ -44,4 +44,9 @@ export const sortOptions: { id: SortField; label: string; category: string }[] =
label: 'name',
category: 'general',
},
{
id: 'health',
label: 'health',
category: 'general',
},
]
60 changes: 60 additions & 0 deletions libs/design-system/src/hooks/useSorting.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
'use client'

import { intersection } from 'lodash'
import { useCallback, useMemo } from 'react'
import useLocalStorageState from 'use-local-storage-state'

type Params<ColumnId extends string, SortField extends string> = {
enabledColumns: ColumnId[]
defaultSortField?: SortField
sortOptions?: { id: SortField }[]
}

export function useSorting<ColumnId extends string, SortField extends string>(
scope: string,
params: Params<ColumnId, SortField>
) {
const { defaultSortField, sortOptions, enabledColumns } = params

const [sortField, setSortField] = useLocalStorageState<SortField>(
`${scope}/sortField`,
{
defaultValue: defaultSortField,
}
)

const [sortDirection, setSortDirection] = useLocalStorageState<
'desc' | 'asc'
>(`${scope}/sortDirection`, {
defaultValue: 'desc',
})

const toggleSort = useCallback(
(field: SortField) => {
if (sortField !== field) {
setSortField(field)
setSortDirection('asc')
return
}
setSortDirection((dir) => (dir === 'desc' ? 'asc' : 'desc'))
},
[sortField, setSortField, setSortDirection]
)

const sortableColumns = useMemo(() => {
if (!sortOptions) {
return []
}
const sortFieldIds = sortOptions.map((o) => o.id)
return intersection(sortFieldIds, enabledColumns as string[]) as SortField[]
}, [sortOptions, enabledColumns])

return {
toggleSort,
setSortDirection,
setSortField,
sortableColumns,
sortField,
sortDirection,
}
}
38 changes: 13 additions & 25 deletions libs/design-system/src/hooks/useTableState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { difference, intersection, uniq } from 'lodash'
import { useCallback, useMemo } from 'react'
import useLocalStorageState from 'use-local-storage-state'
import { useSorting } from './useSorting'

type Column<ColumnId> = {
id: ColumnId
Expand Down Expand Up @@ -44,19 +45,6 @@ export function useTableState<
}
)

const [sortField, setSortField] = useLocalStorageState<SortField>(
`${scope}/sortField`,
{
defaultValue: defaultSortField,
}
)

const [sortDirection, setSortDirection] = useLocalStorageState<
'desc' | 'asc'
>(`${scope}/sortDirection`, {
defaultValue: 'desc',
})

const toggleColumnVisibility = useCallback(
(column: string) => {
setEnabledColumns((enabled) => {
Expand Down Expand Up @@ -91,18 +79,6 @@ export function useTableState<
setEnabledColumns(columnsDefaultVisible)
}, [setEnabledColumns, columnsDefaultVisible])

const toggleSort = useCallback(
(field: SortField) => {
if (sortField !== field) {
setSortField(field)
setSortDirection('asc')
return
}
setSortDirection((dir) => (dir === 'desc' ? 'asc' : 'desc'))
},
[sortField, setSortField, setSortDirection]
)

const configurableColumns = useMemo(
() =>
columns.filter((column) => {
Expand All @@ -129,6 +105,18 @@ export function useTableState<
[columns, _enabledColumns, disabledCategories]
)

const {
sortField,
sortDirection,
setSortField,
setSortDirection,
toggleSort,
} = useSorting(scope, {
defaultSortField,
sortOptions,
enabledColumns,
})

const sortableColumns = useMemo(() => {
if (!sortOptions) {
return []
Expand Down
9 changes: 8 additions & 1 deletion libs/react-renterd/src/bus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,14 @@ export type ObjEntry = {

export function useObjectDirectory(
args: HookArgsSwr<
{ key: string; bucket: string; limit?: number; offset?: number },
{
key: string
bucket: string
limit?: number
offset?: number
sortBy?: 'name' | 'health'
sortDir?: 'asc' | 'desc'
},
{ entries: ObjEntry[] }
>
) {
Expand Down

0 comments on commit 0cb370d

Please sign in to comment.