Skip to content

Commit

Permalink
Add drag and drop to resort connection list
Browse files Browse the repository at this point in the history
Add filter search connection
  • Loading branch information
tiny-craft committed Jul 31, 2023
1 parent d573cab commit 0f29a3c
Show file tree
Hide file tree
Showing 9 changed files with 168 additions and 30 deletions.
11 changes: 11 additions & 0 deletions backend/services/connection_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,17 @@ func (c *connectionService) RemoveConnection(name string) (resp types.JSResp) {
return
}

// SaveSortedConnection save sorted connection after drag
func (c *connectionService) SaveSortedConnection(sortedConns types.Connections) (resp types.JSResp) {
err := c.conns.SaveSortedConnection(sortedConns)
if err != nil {
resp.Msg = err.Error()
return
}
resp.Success = true
return
}

// CreateGroup create new group
func (c *connectionService) CreateGroup(name string) (resp types.JSResp) {
err := c.conns.CreateGroup(name)
Expand Down
42 changes: 42 additions & 0 deletions backend/storage/connections.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"gopkg.in/yaml.v3"
"sync"
"tinyrdm/backend/types"
sliceutil "tinyrdm/backend/utils/slice"
)

type ConnectionsStorage struct {
Expand Down Expand Up @@ -240,6 +241,47 @@ func (c *ConnectionsStorage) RemoveConnection(name string) error {
return c.saveConnections(conns)
}

// SaveSortedConnection save connection after sort
func (c *ConnectionsStorage) SaveSortedConnection(sortedConns types.Connections) error {
c.mutex.Lock()
defer c.mutex.Unlock()

conns := c.GetConnectionsFlat()
takeConn := func(name string) (types.Connection, bool) {
idx, ok := sliceutil.Find(conns, func(i int) bool {
return conns[i].Name == name
})
if ok {
ret := conns[idx]
conns = append(conns[:idx], conns[idx+1:]...)
return ret, true
}
return types.Connection{}, false
}
var replaceConn func(connections types.Connections) types.Connections
replaceConn = func(cons types.Connections) types.Connections {
var newConns types.Connections
for _, conn := range cons {
if conn.Type == "group" {
newConns = append(newConns, types.Connection{
ConnectionConfig: types.ConnectionConfig{
Name: conn.Name,
},
Type: "group",
Connections: replaceConn(conn.Connections),
})
} else {
if foundConn, ok := takeConn(conn.Name); ok {
newConns = append(newConns, foundConn)
}
}
}
return newConns
}
conns = replaceConn(sortedConns)
return c.saveConnections(conns)
}

// CreateGroup create new group
func (c *ConnectionsStorage) CreateGroup(name string) error {
c.mutex.Lock()
Expand Down
2 changes: 1 addition & 1 deletion backend/types/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ type ConnectionCategory int

type ConnectionConfig struct {
Name string `json:"name" yaml:"name"`
Group string `json:"group" yaml:"-"`
Group string `json:"group,omitempty" yaml:"-"`
Addr string `json:"addr,omitempty" yaml:"addr,omitempty"`
Port int `json:"port,omitempty" yaml:"port,omitempty"`
Username string `json:"username,omitempty" yaml:"username,omitempty"`
Expand Down
12 changes: 4 additions & 8 deletions frontend/src/components/sidebar/ConnectionPane.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,11 @@ import Filter from '../icons/Filter.vue'
import ConnectionTree from './ConnectionTree.vue'
import Unlink from '../icons/Unlink.vue'
import useConnectionStore from '../../stores/connections.js'
import { ref } from 'vue'
const dialogStore = useDialogStore()
const connectionStore = useConnectionStore()
const onSort = () => {
dialogStore.openPreferencesDialog()
}
const filterPattern = ref('')
const onDisconnectAll = () => {
connectionStore.closeAllConnection()
Expand All @@ -24,7 +22,7 @@ const onDisconnectAll = () => {

<template>
<div class="nav-pane-container flex-box-v">
<connection-tree />
<connection-tree :filter-pattern="filterPattern" />

<!-- bottom function bar -->
<div class="nav-pane-bottom flex-box-h">
Expand Down Expand Up @@ -53,9 +51,7 @@ const onDisconnectAll = () => {
t-tooltip="disconnect_all"
@click="onDisconnectAll"
/>
<n-divider style="margin: 0 4px; --n-color: #aaa; width: 2px" vertical />
<icon-button :icon="Sort" color="#555" size="20" stroke-width="4" t-tooltip="sort_conn" @click="onSort" />
<n-input placeholder="">
<n-input v-model:value="filterPattern" :placeholder="$t('filter')" clearable>
<template #prefix>
<n-icon :component="Filter" color="#aaa" size="20" />
</template>
Expand Down
69 changes: 64 additions & 5 deletions frontend/src/components/sidebar/ConnectionTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { NIcon, useDialog, useMessage } from 'naive-ui'
import { ConnectionType } from '../../consts/connection_type.js'
import ToggleFolder from '../icons/ToggleFolder.vue'
import ToggleServer from '../icons/ToggleServer.vue'
import { indexOf } from 'lodash'
import { debounce, indexOf, throttle } from 'lodash'
import Config from '../icons/Config.vue'
import Delete from '../icons/Delete.vue'
import Unlink from '../icons/Unlink.vue'
Expand All @@ -28,6 +28,12 @@ const message = useMessage()
const expandedKeys = ref([])
const selectedKeys = ref([])
const props = defineProps({
filterPattern: {
type: String,
},
})
onMounted(async () => {
try {
loadingConnection.value = true
Expand Down Expand Up @@ -152,11 +158,11 @@ const renderPrefix = ({ option }) => {
}
}
const onUpdateExpandedKeys = (keys, option, meta) => {
const onUpdateExpandedKeys = (keys, option) => {
expandedKeys.value = keys
}
const onUpdateSelectedKeys = (keys, option, meta) => {
const onUpdateSelectedKeys = (keys, option) => {
selectedKeys.value = keys
}
Expand Down Expand Up @@ -259,6 +265,56 @@ const handleSelectContextMenu = (key) => {
}
console.warn('TODO: handle context menu:' + key)
}
const findSiblingsAndIndex = (node, nodes) => {
if (!nodes) {
return [null, null]
}
for (let i = 0; i < nodes.length; ++i) {
const siblingNode = nodes[i]
if (siblingNode.key === node.key) {
return [nodes, i]
}
const [siblings, index] = findSiblingsAndIndex(node, siblingNode.children)
if (siblings && index !== null) {
return [siblings, index]
}
}
return [null, null]
}
// delay save until stop drop after 2 seconds
const saveSort = debounce(connectionStore.saveConnectionSort, 2000, { trailing: true })
const handleDrop = ({ node, dragNode, dropPosition }) => {
const [dragNodeSiblings, dragNodeIndex] = findSiblingsAndIndex(dragNode, connectionStore.connections)
if (dragNodeSiblings === null || dragNodeIndex === null) {
return
}
dragNodeSiblings.splice(dragNodeIndex, 1)
if (dropPosition === 'inside') {
if (node.children) {
node.children.unshift(dragNode)
} else {
node.children = [dragNode]
}
} else if (dropPosition === 'before') {
const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, connectionStore.connections)
if (nodeSiblings === null || nodeIndex === null) {
return
}
nodeSiblings.splice(nodeIndex, 0, dragNode)
} else if (dropPosition === 'after') {
const [nodeSiblings, nodeIndex] = findSiblingsAndIndex(node, connectionStore.connections)
if (nodeSiblings === null || nodeIndex === null) {
return
}
nodeSiblings.splice(nodeIndex + 1, 0, dragNode)
}
connectionStore.connections = Array.from(connectionStore.connections)
saveSort()
}
const saveDrop = () => {}
</script>

<template>
Expand All @@ -267,15 +323,18 @@ const handleSelectContextMenu = (key) => {
:block-line="true"
:block-node="true"
:cancelable="false"
:draggable="true"
:data="connectionStore.connections"
:expand-on-click="true"
:expanded-keys="expandedKeys"
:on-update:selected-keys="onUpdateSelectedKeys"
@update:selected-keys="onUpdateSelectedKeys"
:node-props="nodeProps"
:on-update:expanded-keys="onUpdateExpandedKeys"
@update:expanded-keys="onUpdateExpandedKeys"
:selected-keys="selectedKeys"
:render-label="renderLabel"
:render-prefix="renderPrefix"
@drop="handleDrop"
:pattern="props.filterPattern"
class="fill-height"
virtual-scroll
/>
Expand Down
10 changes: 5 additions & 5 deletions frontend/src/components/sidebar/DatabaseTree.vue
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ const expandKey = (key) => {
const message = useMessage()
const dialog = useDialog()
const onUpdateExpanded = (value, option, meta) => {
const onUpdateExpanded = (value, option) => {
expandedKeys.value = value
if (!meta.node) {
return
Expand All @@ -158,7 +158,7 @@ const onUpdateExpanded = (value, option, meta) => {
}
}
const onUpdateSelectedKeys = (keys, option, meta) => {
const onUpdateSelectedKeys = (keys, option) => {
selectedKeys.value = keys
}
Expand Down Expand Up @@ -325,10 +325,10 @@ const handleOutsideContextMenu = () => {
:expand-on-click="false"
:expanded-keys="expandedKeys"
:selected-keys="selectedKeys"
:on-update:selected-keys="onUpdateSelectedKeys"
@update:selected-keys="onUpdateSelectedKeys"
:node-props="nodeProps"
:on-load="onLoadTree"
:on-update:expanded-keys="onUpdateExpanded"
@load="onLoadTree"
@update:expanded-keys="onUpdateExpanded"
:render-label="renderLabel"
:render-prefix="renderPrefix"
:render-suffix="renderSuffix"
Expand Down
1 change: 1 addition & 0 deletions frontend/src/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"new_group": "Add New Group",
"rename_group": "Rename Group",
"disconnect_all": "Disconnect all connections",
"filter": "Filter",
"sort_conn": "Resort Connections",
"reload_key": "Reload Current Key",
"close_confirm": "Confirm close this tab and connection",
Expand Down
1 change: 1 addition & 0 deletions frontend/src/langs/zh-cn.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"new_group": "添加新分组",
"rename_group": "重命名分组",
"disconnect_all": "断开所有连接",
"filter": "筛选",
"sort_conn": "调整连接顺序",
"reload_key": "重新载入此键内容",
"close_confirm": "是否关闭当前连接",
Expand Down
Loading

0 comments on commit 0f29a3c

Please sign in to comment.