feat: add icon function buttons to connection tree items
fix: error cause when close non-connected connection
This commit is contained in:
parent
9fc0cbd40d
commit
484e6a5f6b
|
@ -4,5 +4,6 @@
|
|||
"singleQuote": true,
|
||||
"semi": false,
|
||||
"bracketSameLine": true,
|
||||
"endOfLine": "auto"
|
||||
"endOfLine": "auto",
|
||||
"htmlWhitespaceSensitivity": "ignore"
|
||||
}
|
||||
|
|
|
@ -65,7 +65,6 @@ const valueComponents = {
|
|||
[types.STREAM]: ContentValueStream,
|
||||
}
|
||||
|
||||
const dialog = useDialog()
|
||||
const connectionStore = useConnectionStore()
|
||||
const tabStore = useTabStore()
|
||||
const tab = computed(() =>
|
||||
|
|
|
@ -134,7 +134,6 @@ const infoFilter = ref('')
|
|||
<n-statistic :value="totalKeys">
|
||||
<template #label>
|
||||
{{ $t('total_keys') }}
|
||||
<n-icon :component="Help" />
|
||||
</template>
|
||||
</n-statistic>
|
||||
</n-gi>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<script setup>
|
||||
import { computed, h, nextTick, onMounted, reactive, ref } from 'vue'
|
||||
import { ConnectionType } from '@/consts/connection_type.js'
|
||||
import { NIcon, NSpace, NTag, useDialog } from 'naive-ui'
|
||||
import { NIcon, NSpace, NTag } from 'naive-ui'
|
||||
import Key from '@/components/icons/Key.vue'
|
||||
import ToggleDb from '@/components/icons/ToggleDb.vue'
|
||||
import { find, get, includes, indexOf, isEmpty, remove } from 'lodash'
|
||||
|
@ -22,6 +22,7 @@ import Close from '@/components/icons/Close.vue'
|
|||
import { typesBgColor, typesColor } from '@/consts/support_redis_type.js'
|
||||
import useTabStore from 'stores/tab.js'
|
||||
import IconButton from '@/components/common/IconButton.vue'
|
||||
import { parseHexColor } from '@/utils/rgb.js'
|
||||
|
||||
const props = defineProps({
|
||||
server: String,
|
||||
|
@ -61,13 +62,7 @@ const data = computed(() => {
|
|||
|
||||
const backgroundColor = computed(() => {
|
||||
const { markColor: hex = '' } = connectionStore.serverProfile[props.server] || {}
|
||||
if (isEmpty(hex)) {
|
||||
return ''
|
||||
}
|
||||
const bigint = parseInt(hex.slice(1), 16)
|
||||
const r = (bigint >> 16) & 255
|
||||
const g = (bigint >> 8) & 255
|
||||
const b = bigint & 255
|
||||
const { r, g, b } = parseHexColor(hex)
|
||||
return `rgba(${r}, ${g}, ${b}, 0.2)`
|
||||
})
|
||||
|
||||
|
@ -292,7 +287,6 @@ defineExpose({
|
|||
handleSelectContextMenu,
|
||||
})
|
||||
|
||||
const dialog = useDialog()
|
||||
const onUpdateExpanded = (value, option, meta) => {
|
||||
expandedKeys.value = value
|
||||
if (!meta.node) {
|
||||
|
|
|
@ -2,11 +2,11 @@
|
|||
import useDialogStore from 'stores/dialog.js'
|
||||
import { h, nextTick, reactive, ref } from 'vue'
|
||||
import useConnectionStore from 'stores/connections.js'
|
||||
import { NIcon, useDialog, useThemeVars } from 'naive-ui'
|
||||
import { NIcon, NSpace, NText, useThemeVars } from 'naive-ui'
|
||||
import { ConnectionType } from '@/consts/connection_type.js'
|
||||
import ToggleFolder from '@/components/icons/ToggleFolder.vue'
|
||||
import ToggleServer from '@/components/icons/ToggleServer.vue'
|
||||
import { debounce, indexOf, isEmpty } from 'lodash'
|
||||
import { debounce, get, includes, indexOf, isEmpty, split } from 'lodash'
|
||||
import Config from '@/components/icons/Config.vue'
|
||||
import Delete from '@/components/icons/Delete.vue'
|
||||
import Unlink from '@/components/icons/Unlink.vue'
|
||||
|
@ -15,6 +15,8 @@ import Connect from '@/components/icons/Connect.vue'
|
|||
import { useI18n } from 'vue-i18n'
|
||||
import useTabStore from 'stores/tab.js'
|
||||
import Edit from '@/components/icons/Edit.vue'
|
||||
import { hexGammaCorrection, parseHexColor, toHexColor } from '@/utils/rgb.js'
|
||||
import IconButton from '@/components/common/IconButton.vue'
|
||||
|
||||
const themeVars = useThemeVars()
|
||||
const i18n = useI18n()
|
||||
|
@ -116,9 +118,41 @@ const menuOptions = {
|
|||
}
|
||||
|
||||
const renderLabel = ({ option }) => {
|
||||
if (option.type === ConnectionType.Server) {
|
||||
const { markColor = '' } = connectionStore.serverProfile[option.name] || {}
|
||||
if (!isEmpty(markColor)) {
|
||||
const rgb = parseHexColor(markColor)
|
||||
const rgb2 = hexGammaCorrection(rgb, 0.75)
|
||||
return h(
|
||||
NText,
|
||||
{
|
||||
style: {
|
||||
color: toHexColor(rgb2),
|
||||
},
|
||||
},
|
||||
() => option.label,
|
||||
)
|
||||
}
|
||||
}
|
||||
return option.label
|
||||
}
|
||||
|
||||
// render horizontal item
|
||||
const renderIconMenu = (items) => {
|
||||
return h(
|
||||
NSpace,
|
||||
{
|
||||
align: 'center',
|
||||
inline: true,
|
||||
size: 2,
|
||||
wrapItem: false,
|
||||
wrap: false,
|
||||
style: 'margin-right: 5px',
|
||||
},
|
||||
() => items,
|
||||
)
|
||||
}
|
||||
|
||||
const renderPrefix = ({ option }) => {
|
||||
switch (option.type) {
|
||||
case ConnectionType.Group:
|
||||
|
@ -142,21 +176,67 @@ const renderPrefix = ({ option }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const getServerMenu = (connected) => {
|
||||
const btns = []
|
||||
if (connected) {
|
||||
btns.push(
|
||||
h(IconButton, {
|
||||
tTooltip: 'disconnect',
|
||||
icon: Unlink,
|
||||
onClick: () => handleSelectContextMenu('server_close'),
|
||||
}),
|
||||
h(IconButton, {
|
||||
tTooltip: 'edit_conn',
|
||||
icon: Config,
|
||||
onClick: () => handleSelectContextMenu('server_edit'),
|
||||
}),
|
||||
)
|
||||
} else {
|
||||
btns.push(
|
||||
h(IconButton, {
|
||||
tTooltip: 'open_connection',
|
||||
icon: Connect,
|
||||
onClick: () => handleSelectContextMenu('server_open'),
|
||||
}),
|
||||
h(IconButton, {
|
||||
tTooltip: 'edit_conn',
|
||||
icon: Config,
|
||||
onClick: () => handleSelectContextMenu('server_edit'),
|
||||
}),
|
||||
h(IconButton, {
|
||||
tTooltip: 'remove_conn',
|
||||
icon: Delete,
|
||||
onClick: () => handleSelectContextMenu('server_remove'),
|
||||
}),
|
||||
)
|
||||
}
|
||||
return btns
|
||||
}
|
||||
|
||||
const getGroupMenu = () => {
|
||||
return [
|
||||
h(IconButton, {
|
||||
tTooltip: 'edit_conn',
|
||||
icon: Config,
|
||||
onClick: () => handleSelectContextMenu('group_rename'),
|
||||
}),
|
||||
h(IconButton, {
|
||||
tTooltip: 'remove_conn',
|
||||
icon: Delete,
|
||||
onClick: () => handleSelectContextMenu('group_delete'),
|
||||
}),
|
||||
]
|
||||
}
|
||||
|
||||
const renderSuffix = ({ option }) => {
|
||||
if (option.type === ConnectionType.Server) {
|
||||
const { markColor = '' } = connectionStore.serverProfile[option.name] || {}
|
||||
if (isEmpty(markColor)) {
|
||||
return ''
|
||||
if (includes(selectedKeys.value, option.key)) {
|
||||
switch (option.type) {
|
||||
case ConnectionType.Server:
|
||||
const connected = connectionStore.isConnected(option.name)
|
||||
return renderIconMenu(getServerMenu(connected))
|
||||
case ConnectionType.Group:
|
||||
return renderIconMenu(getGroupMenu())
|
||||
}
|
||||
return h('div', {
|
||||
style: {
|
||||
borderRadius: '50%',
|
||||
backgroundColor: markColor,
|
||||
width: '13px',
|
||||
height: '13px',
|
||||
border: '2px solid white',
|
||||
},
|
||||
})
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
@ -191,7 +271,6 @@ const openConnection = async (name) => {
|
|||
}
|
||||
}
|
||||
|
||||
const dialog = useDialog()
|
||||
const removeConnection = (name) => {
|
||||
$dialog.warning(i18n.t('remove_tip', { type: i18n.t('conn_name'), name }), async () => {
|
||||
connectionStore.deleteConnection(name).then(({ success, msg }) => {
|
||||
|
@ -203,7 +282,7 @@ const removeConnection = (name) => {
|
|||
}
|
||||
|
||||
const removeGroup = async (name) => {
|
||||
$dialog.warning(i18n.t('remove_tip', { type: i18n.t('conn_group'), name }), async () => {
|
||||
$dialog.warning(i18n.t('remove_group_tip', { name }), async () => {
|
||||
connectionStore.deleteGroup(name).then(({ success, msg }) => {
|
||||
if (!success) {
|
||||
$message.error(msg)
|
||||
|
@ -256,7 +335,14 @@ const renderContextLabel = (option) => {
|
|||
|
||||
const handleSelectContextMenu = (key) => {
|
||||
contextMenuParam.show = false
|
||||
const { name, label, db, key: nodeKey, redisKey } = contextMenuParam.currentNode
|
||||
const selectedKey = get(selectedKeys.value, 0)
|
||||
if (selectedKey == null) {
|
||||
return
|
||||
}
|
||||
const [group, name] = split(selectedKey, '/')
|
||||
if (isEmpty(group) && isEmpty(name)) {
|
||||
return
|
||||
}
|
||||
switch (key) {
|
||||
case 'server_open':
|
||||
openConnection(name).then(() => {})
|
||||
|
@ -276,13 +362,17 @@ const handleSelectContextMenu = (key) => {
|
|||
removeConnection(name)
|
||||
break
|
||||
case 'server_close':
|
||||
connectionStore.closeConnection(name)
|
||||
if (!isEmpty(group)) {
|
||||
connectionStore.closeConnection(name)
|
||||
}
|
||||
break
|
||||
case 'group_rename':
|
||||
dialogStore.openRenameGroupDialog(label)
|
||||
if (!isEmpty(group)) {
|
||||
dialogStore.openRenameGroupDialog(group)
|
||||
}
|
||||
break
|
||||
case 'group_delete':
|
||||
removeGroup(label)
|
||||
removeGroup(group)
|
||||
break
|
||||
default:
|
||||
console.warn('TODO: handle context menu:' + key)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"edit_close_confirm": "Please close the relevant connections before editing. Do you want to continue?",
|
||||
"opening_connection": "Opening Connection...",
|
||||
"remove_tip": "{type} \"{name}\" will be deleted",
|
||||
"remove_group_tip": "Group \"{name}\" and all connections in it will be deleted",
|
||||
"ttl": "TTL",
|
||||
"forever": "Forever",
|
||||
"rename_key": "Rename Key",
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
"edit_close_confirm": "编辑前需要关闭相关连接,是否继续",
|
||||
"opening_connection": "正在打开连接...",
|
||||
"remove_tip": "{type} \"{name}\" 将会被删除",
|
||||
"remove_group_tip": "分组 \"{name}\"及其所有连接将会被删除",
|
||||
"ttl": "TTL",
|
||||
"forever": "永久",
|
||||
"rename_key": "重命名键",
|
||||
|
|
|
@ -124,7 +124,7 @@ const useConnectionStore = defineStore('connections', {
|
|||
if (conn.type !== 'group') {
|
||||
// top level
|
||||
conns.push({
|
||||
key: conn.name,
|
||||
key: '/' + conn.name,
|
||||
label: conn.name,
|
||||
name: conn.name,
|
||||
type: ConnectionType.Server,
|
||||
|
@ -151,7 +151,7 @@ const useConnectionStore = defineStore('connections', {
|
|||
})
|
||||
}
|
||||
conns.push({
|
||||
key: conn.name,
|
||||
key: conn.name + '/',
|
||||
label: conn.name,
|
||||
type: ConnectionType.Group,
|
||||
children,
|
||||
|
@ -346,9 +346,11 @@ const useConnectionStore = defineStore('connections', {
|
|||
}
|
||||
|
||||
const dbs = this.databases[name]
|
||||
for (const db of dbs) {
|
||||
this.removeKeyFilter(name, db.db)
|
||||
this._getNodeMap(name, db.db).clear()
|
||||
if (!isEmpty(dbs)) {
|
||||
for (const db of dbs) {
|
||||
this.removeKeyFilter(name, db.db)
|
||||
this._getNodeMap(name, db.db).clear()
|
||||
}
|
||||
}
|
||||
this.removeKeyFilter(name, -1)
|
||||
delete this.databases[name]
|
||||
|
|
|
@ -76,6 +76,7 @@ const useDialogStore = defineStore('dialog', {
|
|||
},
|
||||
|
||||
openNewGroupDialog() {
|
||||
this.editGroup = ''
|
||||
this.groupDialogVisible = true
|
||||
},
|
||||
closeNewGroupDialog() {
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
import { padStart, size, startsWith } from 'lodash'
|
||||
|
||||
/**
|
||||
* @typedef {Object} RGB
|
||||
* @property {number} r
|
||||
* @property {number} g
|
||||
* @property {number} b
|
||||
*/
|
||||
|
||||
/**
|
||||
* parse hex color to rgb object
|
||||
* @param hex
|
||||
* @return {RGB}
|
||||
*/
|
||||
export function parseHexColor(hex) {
|
||||
if (size(hex) < 6) {
|
||||
return { r: 0, g: 0, b: 0 }
|
||||
}
|
||||
if (startsWith(hex, '#')) {
|
||||
hex = hex.slice(1)
|
||||
}
|
||||
const bigint = parseInt(hex, 16)
|
||||
const r = (bigint >> 16) & 255
|
||||
const g = (bigint >> 8) & 255
|
||||
const b = bigint & 255
|
||||
return { r, g, b }
|
||||
}
|
||||
|
||||
/**
|
||||
* do gamma correction with an RGB object
|
||||
* @param {RGB} rgb
|
||||
* @param {Number} gamma
|
||||
* @return {RGB}
|
||||
*/
|
||||
export function hexGammaCorrection(rgb, gamma) {
|
||||
if (typeof rgb !== 'object') {
|
||||
return { r: 0, g: 0, b: 0 }
|
||||
}
|
||||
return {
|
||||
r: Math.max(0, Math.min(255, Math.round(rgb.r * gamma))),
|
||||
g: Math.max(0, Math.min(255, Math.round(rgb.g * gamma))),
|
||||
b: Math.max(0, Math.min(255, Math.round(rgb.b * gamma))),
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* RGB object to hex color string
|
||||
* @param {RGB} rgb
|
||||
* @return {string}
|
||||
*/
|
||||
export function toHexColor(rgb) {
|
||||
return (
|
||||
'#' +
|
||||
padStart(rgb.r.toString(16), 2, '0') +
|
||||
padStart(rgb.g.toString(16), 2, '0') +
|
||||
padStart(rgb.b.toString(16), 2, '0')
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue