feat: sortable column

This commit is contained in:
Zephyruso 2023-09-01 00:12:33 +08:00
parent be35f499ae
commit 4c4011a617
4 changed files with 123 additions and 28 deletions

View File

@ -21,6 +21,7 @@
"@tabler/icons-solidjs": "^2.32.0", "@tabler/icons-solidjs": "^2.32.0",
"@tanstack/solid-table": "^8.9.3", "@tanstack/solid-table": "^8.9.3",
"@tanstack/solid-virtual": "3.0.0-beta.6", "@tanstack/solid-virtual": "3.0.0-beta.6",
"@thisbeyond/solid-dnd": "^0.7.4",
"@types/byte-size": "^8.1.0", "@types/byte-size": "^8.1.0",
"@types/node": "^20.5.7", "@types/node": "^20.5.7",
"@types/uuid": "^9.0.3", "@types/uuid": "^9.0.3",

View File

@ -35,6 +35,9 @@ dependencies:
'@tanstack/solid-virtual': '@tanstack/solid-virtual':
specifier: 3.0.0-beta.6 specifier: 3.0.0-beta.6
version: 3.0.0-beta.6 version: 3.0.0-beta.6
'@thisbeyond/solid-dnd':
specifier: ^0.7.4
version: 0.7.4(solid-js@1.7.11)
'@types/byte-size': '@types/byte-size':
specifier: ^8.1.0 specifier: ^8.1.0
version: 8.1.0 version: 8.1.0
@ -1296,6 +1299,17 @@ packages:
engines: { node: '>=12' } engines: { node: '>=12' }
dev: false dev: false
/@thisbeyond/solid-dnd@0.7.4(solid-js@1.7.11):
resolution:
{
integrity: sha512-jgV9EtR3gAtVsILG8p1OAGrhHIgnK4W04YxpyLgJRCDKEFYQWuDrMdUe8F5Kc6pcVXlC4IMXr4cB8fS2Ut3/Ow==,
}
peerDependencies:
solid-js: ^1.5
dependencies:
solid-js: 1.7.11
dev: false
/@tsconfig/node10@1.0.9: /@tsconfig/node10@1.0.9:
resolution: resolution:
{ {

View File

@ -1,41 +1,105 @@
import { For } from 'solid-js' import type {
DragEventHandler,
Draggable,
Droppable,
} from '@thisbeyond/solid-dnd'
import {
DragDropProvider,
DragDropSensors,
DragOverlay,
SortableProvider,
closestCenter,
createSortable,
useDragDropContext,
} from '@thisbeyond/solid-dnd'
import { For, createSignal } from 'solid-js'
import { AccessorKey } from '~/config/connection' import { AccessorKey } from '~/config/connection'
type ColumnVisibility = Partial<Record<AccessorKey, boolean>> type ColumnVisibility = Partial<Record<AccessorKey, boolean>>
type ColumnOrder = AccessorKey[]
export default (props: { export default (props: {
data: ColumnVisibility order: ColumnOrder
onChange: (value: ColumnVisibility) => void visible: ColumnVisibility
onOrderChange: (value: ColumnOrder) => void
onVisibleChange: (value: ColumnVisibility) => void
}) => { }) => {
const { onChange } = props const [activeKey, setActiveKey] = createSignal<AccessorKey | null>(null)
const onDragStart = ({ draggable }: { draggable: Draggable }) =>
setActiveKey(draggable.id as AccessorKey)
const onDragEnd = ({
draggable,
droppable,
}: {
draggable: Draggable
droppable: Droppable
}) => {
if (draggable && droppable) {
const currentItems = props.order
const fromIndex = currentItems.indexOf(draggable.id as AccessorKey)
const toIndex = currentItems.indexOf(droppable.id as AccessorKey)
if (fromIndex !== toIndex) {
const updatedItems = currentItems.slice()
updatedItems.splice(toIndex, 0, ...updatedItems.splice(fromIndex, 1))
props.onOrderChange(updatedItems)
}
}
}
const FormRow = (p: { key: AccessorKey }) => {
const key = p.key
const sortable = createSortable(key)
const [state] = useDragDropContext()!
return (
<div
use:sortable
class="sortable"
classList={{
'opacity-25': sortable.isActiveDraggable,
'transition-transform': !!state.active.draggable,
}}
>
<div class="m-1 flex cursor-pointer justify-between p-1">
<span class="select-none">{key}</span>
<input
type="checkbox"
class="toggle"
checked={props.visible[key]}
onChange={(e) => {
props.onVisibleChange({
...props.visible,
[key]: e.target.checked,
})
}}
/>
</div>
</div>
)
}
return ( return (
<> <>
<input type="checkbox" id="connection-modal" class="modal-toggle" /> <input type="checkbox" id="connection-modal" class="modal-toggle" />
<div class="modal"> <div class="modal">
<div class="modal-box w-80"> <div class="modal-box w-80">
<For <DragDropProvider
each={Object.values(AccessorKey).filter( onDragStart={onDragStart}
(i) => ![AccessorKey.Close, AccessorKey.ID].includes(i), onDragEnd={onDragEnd as DragEventHandler}
)} collisionDetector={closestCenter}
> >
{(key) => ( <DragDropSensors />
<div class="m-1 flex justify-between p-1"> <div class="column self-stretch">
{key} <SortableProvider ids={props.order}>
<input <For each={props.order}>{(key) => <FormRow key={key} />}</For>
type="checkbox" </SortableProvider>
class="toggle" </div>
checked={props.data[key]} <DragOverlay>
onChange={(e) => { <div class="sortable">{activeKey()}</div>
onChange({ </DragOverlay>
...props.data, </DragDropProvider>
[key]: e.target.checked,
})
}}
/>
</div>
)}
</For>
</div> </div>
<label class="modal-backdrop" htmlFor="connection-modal"> <label class="modal-backdrop" htmlFor="connection-modal">
Close Close

View File

@ -30,9 +30,11 @@ type ConnectionWithSpeed = Connection & {
} }
type ColumnVisibility = Partial<Record<AccessorKey, boolean>> type ColumnVisibility = Partial<Record<AccessorKey, boolean>>
type ColumnOrder = AccessorKey[]
const initColumnOrder = Object.values(AccessorKey)
const initColumnVisibility = { const initColumnVisibility = {
...Object.fromEntries(Object.values(AccessorKey).map((i) => [i, true])), ...Object.fromEntries(initColumnOrder.map((i) => [i, true])),
[AccessorKey.ID]: false, [AccessorKey.ID]: false,
} }
@ -44,6 +46,13 @@ export default () => {
storage: localStorage, storage: localStorage,
}, },
) )
const [columnOrder, setColumnOrder] = makePersisted(
createSignal<ColumnOrder>(initColumnOrder),
{
name: 'columnOrder',
storage: localStorage,
},
)
const request = useRequest() const request = useRequest()
const [search, setSearch] = createSignal('') const [search, setSearch] = createSignal('')
@ -192,6 +201,9 @@ export default () => {
const table = createSolidTable({ const table = createSolidTable({
state: { state: {
get columnOrder() {
return columnOrder()
},
get sorting() { get sorting() {
return sorting() return sorting()
}, },
@ -229,8 +241,12 @@ export default () => {
<IconSettings /> <IconSettings />
</label> </label>
<ConnectionsModal <ConnectionsModal
data={columnVisibility()} order={columnOrder()}
onChange={(data: ColumnVisibility) => visible={columnVisibility()}
onOrderChange={(data: ColumnOrder) => {
setColumnOrder([...data])
}}
onVisibleChange={(data: ColumnVisibility) =>
setColumnVisibility({ ...data }) setColumnVisibility({ ...data })
} }
/> />