mirror of
https://github.com/thomasnordquist/MQTT-Explorer.git
synced 2026-07-27 19:56:50 +00:00
Replace arrow buttons with drag-and-drop reordering using drag handles
Co-authored-by: thomasnordquist <7721625+thomasnordquist@users.noreply.github.com>
This commit is contained in:
co-authored by
thomasnordquist
parent
1a8a9224b4
commit
be83c3f2cc
@@ -1,7 +1,7 @@
|
||||
import React, { useCallback } from 'react'
|
||||
import { connect } from 'react-redux'
|
||||
import { ListItem, Typography, IconButton, Box } from '@mui/material'
|
||||
import { ArrowUpward, ArrowDownward } from '@mui/icons-material'
|
||||
import { ListItem, Typography, Box } from '@mui/material'
|
||||
import { DragIndicator } from '@mui/icons-material'
|
||||
import { toMqttConnection, ConnectionOptions } from '../../../model/ConnectionOptions'
|
||||
import { withStyles } from '@mui/styles'
|
||||
import { Theme } from '@mui/material/styles'
|
||||
@@ -16,6 +16,9 @@ export interface Props {
|
||||
}
|
||||
selected: boolean
|
||||
classes: any
|
||||
onDragStart: (connectionId: string) => void
|
||||
onDragOver: (e: React.DragEvent) => void
|
||||
onDrop: (connectionId: string) => void
|
||||
}
|
||||
|
||||
const ConnectionItem = (props: Props) => {
|
||||
@@ -26,14 +29,21 @@ const ConnectionItem = (props: Props) => {
|
||||
}
|
||||
}, [props.connection, props])
|
||||
|
||||
const handleMoveUp = (e: React.MouseEvent) => {
|
||||
const handleDragStart = (e: React.DragEvent) => {
|
||||
e.stopPropagation()
|
||||
props.actions.connectionManager.moveConnection(props.connection.id, 'up')
|
||||
props.onDragStart(props.connection.id)
|
||||
}
|
||||
|
||||
const handleMoveDown = (e: React.MouseEvent) => {
|
||||
const handleDragOver = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
props.actions.connectionManager.moveConnection(props.connection.id, 'down')
|
||||
props.onDragOver(e)
|
||||
}
|
||||
|
||||
const handleDrop = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
props.onDrop(props.connection.id)
|
||||
}
|
||||
|
||||
const connection = props.connection.host && toMqttConnection(props.connection)
|
||||
@@ -47,19 +57,20 @@ const ConnectionItem = (props: Props) => {
|
||||
props.actions.connectionManager.selectConnection(props.connection.id)
|
||||
connect()
|
||||
}}
|
||||
onDragOver={handleDragOver}
|
||||
onDrop={handleDrop}
|
||||
>
|
||||
<Box
|
||||
className={props.classes.dragHandle}
|
||||
draggable
|
||||
onDragStart={handleDragStart}
|
||||
>
|
||||
<DragIndicator fontSize="small" />
|
||||
</Box>
|
||||
<Box className={props.classes.textContainer}>
|
||||
<Typography className={props.classes.name}>{props.connection.name || 'mqtt broker'}</Typography>
|
||||
<Typography className={props.classes.details}>{connection && connection.url}</Typography>
|
||||
</Box>
|
||||
<Box className={props.classes.buttonContainer}>
|
||||
<IconButton size="small" onClick={handleMoveUp} className={props.classes.arrowButton}>
|
||||
<ArrowUpward fontSize="small" />
|
||||
</IconButton>
|
||||
<IconButton size="small" onClick={handleMoveDown} className={props.classes.arrowButton}>
|
||||
<ArrowDownward fontSize="small" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
</ListItem>
|
||||
)
|
||||
}
|
||||
@@ -90,19 +101,21 @@ export const connectionItemStyle = (theme: Theme) => ({
|
||||
itemContainer: {
|
||||
display: 'flex' as 'flex',
|
||||
alignItems: 'center' as 'center',
|
||||
padding: '8px 8px 8px 16px',
|
||||
padding: '8px 8px 8px 8px',
|
||||
},
|
||||
textContainer: {
|
||||
flex: 1,
|
||||
overflow: 'hidden' as 'hidden',
|
||||
},
|
||||
buttonContainer: {
|
||||
dragHandle: {
|
||||
display: 'flex' as 'flex',
|
||||
flexDirection: 'column' as 'column',
|
||||
marginLeft: '4px',
|
||||
},
|
||||
arrowButton: {
|
||||
padding: '2px',
|
||||
alignItems: 'center' as 'center',
|
||||
marginRight: '8px',
|
||||
cursor: 'grab' as 'grab',
|
||||
color: theme.palette.text.secondary,
|
||||
'&:active': {
|
||||
cursor: 'grabbing' as 'grabbing',
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import ConnectionItem from './ConnectionItem'
|
||||
const ConnectionItemAny = ConnectionItem as any
|
||||
import React from 'react'
|
||||
import React, { useState } from 'react'
|
||||
import { AddButton } from './AddButton'
|
||||
import { AppState } from '../../../reducers'
|
||||
import { bindActionCreators } from 'redux'
|
||||
@@ -22,6 +22,7 @@ interface Props {
|
||||
|
||||
function ProfileList(props: Props) {
|
||||
const { actions, classes, connections, selected } = props
|
||||
const [draggedConnectionId, setDraggedConnectionId] = useState<string | null>(null)
|
||||
|
||||
const selectConnection = (dir: 'next' | 'previous') => (event: KeyboardEvent) => {
|
||||
if (!selected) {
|
||||
@@ -40,6 +41,39 @@ function ProfileList(props: Props) {
|
||||
useGlobalKeyEventHandler(KeyCodes.arrow_down, selectConnection('next'))
|
||||
useGlobalKeyEventHandler(KeyCodes.arrow_up, selectConnection('previous'))
|
||||
|
||||
const handleDragStart = (connectionId: string) => {
|
||||
setDraggedConnectionId(connectionId)
|
||||
}
|
||||
|
||||
const handleDragOver = (e: React.DragEvent) => {
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
const handleDrop = (targetConnectionId: string) => {
|
||||
if (!draggedConnectionId || draggedConnectionId === targetConnectionId) {
|
||||
setDraggedConnectionId(null)
|
||||
return
|
||||
}
|
||||
|
||||
const sortedConnections = Object.values(connections).sort((a, b) => (a.order || 0) - (b.order || 0))
|
||||
const draggedIndex = sortedConnections.findIndex(c => c.id === draggedConnectionId)
|
||||
const targetIndex = sortedConnections.findIndex(c => c.id === targetConnectionId)
|
||||
|
||||
if (draggedIndex === -1 || targetIndex === -1) {
|
||||
setDraggedConnectionId(null)
|
||||
return
|
||||
}
|
||||
|
||||
// Swap order values
|
||||
const draggedConnection = sortedConnections[draggedIndex]
|
||||
const targetConnection = sortedConnections[targetIndex]
|
||||
|
||||
actions.updateConnection(draggedConnection.id, { order: targetConnection.order })
|
||||
actions.updateConnection(targetConnection.id, { order: draggedConnection.order })
|
||||
|
||||
setDraggedConnectionId(null)
|
||||
}
|
||||
|
||||
const createConnectionButton = (
|
||||
<div style={{ padding: '8px 16px' }}>
|
||||
<AddButton action={actions.createConnection} />
|
||||
@@ -53,7 +87,14 @@ function ProfileList(props: Props) {
|
||||
{Object.values(connections)
|
||||
.sort((a, b) => (a.order || 0) - (b.order || 0))
|
||||
.map(connection => (
|
||||
<ConnectionItemAny connection={connection} key={connection.id} selected={selected === connection.id} />
|
||||
<ConnectionItemAny
|
||||
connection={connection}
|
||||
key={connection.id}
|
||||
selected={selected === connection.id}
|
||||
onDragStart={handleDragStart}
|
||||
onDragOver={handleDragOver}
|
||||
onDrop={handleDrop}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</List>
|
||||
|
||||
Reference in New Issue
Block a user