feat(connections): fuzzy filter

This commit is contained in:
kunish 2023-09-10 17:55:53 +08:00
parent e7eb3dd331
commit 9a144e882d
No known key found for this signature in database
GPG Key ID: 647A12B4F782C430
5 changed files with 81 additions and 33 deletions

View File

@ -26,6 +26,7 @@
"@solid-primitives/websocket": "^1.1.0", "@solid-primitives/websocket": "^1.1.0",
"@solidjs/router": "^0.8.3", "@solidjs/router": "^0.8.3",
"@tabler/icons-solidjs": "^2.34.0", "@tabler/icons-solidjs": "^2.34.0",
"@tanstack/match-sorter-utils": "^8.8.4",
"@tanstack/solid-table": "^8.9.7", "@tanstack/solid-table": "^8.9.7",
"@tanstack/solid-virtual": "3.0.0-beta.6", "@tanstack/solid-virtual": "3.0.0-beta.6",
"@thisbeyond/solid-dnd": "^0.7.4", "@thisbeyond/solid-dnd": "^0.7.4",

20
pnpm-lock.yaml generated
View File

@ -50,6 +50,9 @@ dependencies:
'@tabler/icons-solidjs': '@tabler/icons-solidjs':
specifier: ^2.34.0 specifier: ^2.34.0
version: 2.34.0(solid-js@1.7.11) version: 2.34.0(solid-js@1.7.11)
'@tanstack/match-sorter-utils':
specifier: ^8.8.4
version: 8.8.4
'@tanstack/solid-table': '@tanstack/solid-table':
specifier: ^8.9.7 specifier: ^8.9.7
version: 8.9.7(solid-js@1.7.11) version: 8.9.7(solid-js@1.7.11)
@ -2763,6 +2766,16 @@ packages:
} }
dev: false dev: false
/@tanstack/match-sorter-utils@8.8.4:
resolution:
{
integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==,
}
engines: { node: '>=12' }
dependencies:
remove-accents: 0.4.2
dev: false
/@tanstack/solid-table@8.9.7(solid-js@1.7.11): /@tanstack/solid-table@8.9.7(solid-js@1.7.11):
resolution: resolution:
{ {
@ -6841,6 +6854,13 @@ packages:
jsesc: 0.5.0 jsesc: 0.5.0
dev: false dev: false
/remove-accents@0.4.2:
resolution:
{
integrity: sha512-7pXIJqJOq5tFgG1A2Zxti3Ht8jJF337m4sowbuHsW30ZnkQFnDzy9qBNhgzX8ZLW4+UBcXiiR7SwR6pokHsxiA==,
}
dev: false
/require-directory@2.1.1: /require-directory@2.1.1:
resolution: resolution:
{ {

View File

@ -0,0 +1,30 @@
import { Component, Show } from 'solid-js'
import { allConnections } from '~/signals'
export const ConnectionsTableDetailsModal: Component<{
selectedConnectionID?: string
}> = (props) => {
return (
<dialog id="connections-table-details-modal" class="modal">
<div class="modal-box">
<Show when={props.selectedConnectionID}>
<pre>
<code>
{JSON.stringify(
allConnections.find(
({ id }) => id === props.selectedConnectionID,
),
null,
2,
)}
</code>
</pre>
</Show>
</div>
<form method="dialog" class="modal-backdrop">
<button />
</form>
</dialog>
)
}

View File

@ -1,5 +1,6 @@
export * from './Button' export * from './Button'
export * from './Collapse' export * from './Collapse'
export * from './ConnectionsTableDetailsModal'
export * from './ConnectionsTableOrderingModal' export * from './ConnectionsTableOrderingModal'
export * from './ForTwoColumns' export * from './ForTwoColumns'
export * from './Header' export * from './Header'

View File

@ -13,8 +13,10 @@ import {
IconZoomInFilled, IconZoomInFilled,
IconZoomOutFilled, IconZoomOutFilled,
} from '@tabler/icons-solidjs' } from '@tabler/icons-solidjs'
import { rankItem } from '@tanstack/match-sorter-utils'
import { import {
ColumnDef, ColumnDef,
FilterFn,
GroupingState, GroupingState,
SortingState, SortingState,
createSolidTable, createSolidTable,
@ -27,9 +29,13 @@ import {
} from '@tanstack/solid-table' } from '@tanstack/solid-table'
import byteSize from 'byte-size' import byteSize from 'byte-size'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { Component, For, Show, createMemo, createSignal } from 'solid-js' import { For, createMemo, createSignal } from 'solid-js'
import { twMerge } from 'tailwind-merge' import { twMerge } from 'tailwind-merge'
import { Button, ConnectionsTableOrderingModal } from '~/components' import {
Button,
ConnectionsTableDetailsModal,
ConnectionsTableOrderingModal,
} from '~/components'
import { import {
CONNECTIONS_TABLE_ACCESSOR_KEY, CONNECTIONS_TABLE_ACCESSOR_KEY,
CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER, CONNECTIONS_TABLE_INITIAL_COLUMN_ORDER,
@ -37,7 +43,6 @@ import {
} from '~/constants' } from '~/constants'
import { formatTimeFromNow } from '~/helpers' import { formatTimeFromNow } from '~/helpers'
import { import {
allConnections,
tableSize, tableSize,
tableSizeClassName, tableSizeClassName,
useConnections, useConnections,
@ -53,39 +58,23 @@ enum ActiveTab {
closedConnections = 'closedConnections', closedConnections = 'closedConnections',
} }
const ConnectionDetailsModal: Component<{ const fuzzyFilter: FilterFn<Connection> = (row, columnId, value, addMeta) => {
selectedConnectionID?: string // Rank the item
}> = (props) => { const itemRank = rankItem(row.getValue(columnId), value)
return (
<dialog id="connections-table-details-modal" class="modal">
<div class="modal-box">
<Show when={props.selectedConnectionID}>
<pre>
<code>
{JSON.stringify(
allConnections.find(
({ id }) => id === props.selectedConnectionID,
),
null,
2,
)}
</code>
</pre>
</Show>
</div>
<form method="dialog" class="modal-backdrop"> // Store the itemRank info
<button /> addMeta({
</form> itemRank,
</dialog> })
)
// Return if the item should be filtered in/out
return itemRank.passed
} }
export default () => { export default () => {
const [t] = useI18n() const [t] = useI18n()
const request = useRequest() const request = useRequest()
const [search, setSearch] = createSignal('')
const [activeTab, setActiveTab] = createSignal(ActiveTab.activeConnections) const [activeTab, setActiveTab] = createSignal(ActiveTab.activeConnections)
const { activeConnections, closedConnections, paused, setPaused } = const { activeConnections, closedConnections, paused, setPaused } =
useConnections() useConnections()
@ -93,6 +82,7 @@ export default () => {
const onSingleConnectionClose = (id: string) => const onSingleConnectionClose = (id: string) =>
request.delete(`connections/${id}`) request.delete(`connections/${id}`)
const [globalFilter, setGlobalFilter] = createSignal('')
const [columnVisibility, setColumnVisibility] = makePersisted( const [columnVisibility, setColumnVisibility] = makePersisted(
createSignal<ColumnVisibility>(CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY), createSignal<ColumnVisibility>(CONNECTIONS_TABLE_INITIAL_COLUMN_VISIBILITY),
{ {
@ -267,6 +257,9 @@ export default () => {
) )
const table = createSolidTable({ const table = createSolidTable({
filterFns: {
fuzzy: fuzzyFilter,
},
state: { state: {
get columnOrder() { get columnOrder() {
return columnOrder() return columnOrder()
@ -281,7 +274,7 @@ export default () => {
return columnVisibility() return columnVisibility()
}, },
get globalFilter() { get globalFilter() {
return search() return globalFilter()
}, },
get columnFilters() { get columnFilters() {
return [] return []
@ -295,7 +288,8 @@ export default () => {
sortDescFirst: true, sortDescFirst: true,
enableHiding: true, enableHiding: true,
columns: columns(), columns: columns(),
onGlobalFilterChange: setSearch, onGlobalFilterChange: setGlobalFilter,
globalFilterFn: fuzzyFilter,
onGroupingChange: setGrouping, onGroupingChange: setGrouping,
onSortingChange: setSorting, onSortingChange: setSorting,
getFilteredRowModel: getFilteredRowModel(), getFilteredRowModel: getFilteredRowModel(),
@ -343,7 +337,7 @@ export default () => {
type="search" type="search"
class="input join-item input-primary flex-1 sm:input-md" class="input join-item input-primary flex-1 sm:input-md"
placeholder={t('search')} placeholder={t('search')}
onInput={(e) => setSearch(e.target.value)} onInput={(e) => setGlobalFilter(e.target.value)}
/> />
<Button <Button
@ -521,7 +515,9 @@ export default () => {
} }
/> />
<ConnectionDetailsModal selectedConnectionID={selectedConnectionID()} /> <ConnectionsTableDetailsModal
selectedConnectionID={selectedConnectionID()}
/>
</div> </div>
) )
} }