feat: add type display in key browser
This commit is contained in:
parent
b688ded610
commit
af6b4257f9
|
@ -516,6 +516,35 @@ func (b *browserService) LoadAllKeys(connName string, db int, match, keyType str
|
|||
return
|
||||
}
|
||||
|
||||
func (b *browserService) GetKeyType(param types.KeySummaryParam) (resp types.JSResp) {
|
||||
item, err := b.getRedisClient(param.Server, param.DB)
|
||||
if err != nil {
|
||||
resp.Msg = err.Error()
|
||||
return
|
||||
}
|
||||
|
||||
client, ctx := item.client, item.ctx
|
||||
key := strutil.DecodeRedisKey(param.Key)
|
||||
var keyType string
|
||||
keyType, err = client.Type(ctx, key).Result()
|
||||
if err != nil {
|
||||
resp.Msg = err.Error()
|
||||
return
|
||||
}
|
||||
|
||||
if keyType == "none" {
|
||||
resp.Msg = "key not exists"
|
||||
return
|
||||
}
|
||||
|
||||
var data types.KeySummary
|
||||
data.Type = strings.ToLower(keyType)
|
||||
|
||||
resp.Success = true
|
||||
resp.Data = data
|
||||
return
|
||||
}
|
||||
|
||||
// GetKeySummary get key summary info
|
||||
func (b *browserService) GetKeySummary(param types.KeySummaryParam) (resp types.JSResp) {
|
||||
item, err := b.getRedisClient(param.Server, param.DB)
|
||||
|
|
|
@ -14,9 +14,9 @@ type KeySummaryParam struct {
|
|||
|
||||
type KeySummary struct {
|
||||
Type string `json:"type"`
|
||||
TTL int64 `json:"ttl"`
|
||||
Size int64 `json:"size"`
|
||||
Length int64 `json:"length"`
|
||||
TTL int64 `json:"ttl,omitempty"`
|
||||
Size int64 `json:"size,omitempty"`
|
||||
Length int64 `json:"length,omitempty"`
|
||||
}
|
||||
|
||||
type KeyDetailParam struct {
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
import ContentPane from './components/content/ContentPane.vue'
|
||||
import BrowserPane from './components/sidebar/BrowserPane.vue'
|
||||
import { computed, onMounted, reactive, ref, watch } from 'vue'
|
||||
import { debounce, get } from 'lodash'
|
||||
import { debounce } from 'lodash'
|
||||
import { useThemeVars } from 'naive-ui'
|
||||
import Ribbon from './components/sidebar/Ribbon.vue'
|
||||
import ConnectionPane from './components/sidebar/ConnectionPane.vue'
|
||||
|
@ -139,7 +139,7 @@ onMounted(async () => {
|
|||
<div style="min-width: 68px; font-weight: 800">Tiny RDM</div>
|
||||
<transition name="fade">
|
||||
<n-text v-if="tabStore.nav === 'browser'" class="ellipsis" strong style="font-size: 13px">
|
||||
- {{ get(tabStore.currentTab, 'name') }}
|
||||
- {{ tabStore.currentTabName }}
|
||||
</n-text>
|
||||
</transition>
|
||||
</n-space>
|
||||
|
@ -174,13 +174,15 @@ onMounted(async () => {
|
|||
@update:size="handleResize">
|
||||
<browser-pane
|
||||
v-for="t in tabStore.tabs"
|
||||
v-show="get(tabStore.currentTab, 'name') === t.name"
|
||||
v-show="tabStore.currentTabName === t.name"
|
||||
:key="t.name"
|
||||
:db="t.db"
|
||||
:server="t.name"
|
||||
class="app-side flex-item-expand" />
|
||||
</resizeable-wrapper>
|
||||
<content-pane
|
||||
v-for="t in tabStore.tabs"
|
||||
v-show="get(tabStore.currentTab, 'name') === t.name"
|
||||
v-show="tabStore.currentTabName === t.name"
|
||||
:key="t.name"
|
||||
:server="t.name"
|
||||
class="flex-item-expand" />
|
||||
|
|
|
@ -3,6 +3,7 @@ import { computed, h } from 'vue'
|
|||
import { useThemeVars } from 'naive-ui'
|
||||
import { types, typesBgColor, typesColor } from '@/consts/support_redis_type.js'
|
||||
import { get, map, toUpper } from 'lodash'
|
||||
import RedisTypeTag from '@/components/common/RedisTypeTag.vue'
|
||||
|
||||
const props = defineProps({
|
||||
value: {
|
||||
|
@ -23,15 +24,24 @@ const options = computed(() => {
|
|||
|
||||
const themeVars = useThemeVars()
|
||||
const renderIcon = (option) => {
|
||||
if (option.key === props.value) {
|
||||
const backgroundColor = get(typesColor, option.key, themeVars.value.textColor3)
|
||||
return h('div', { style: { borderRadius: '999px', width: '10px', height: '10px', backgroundColor } }, '')
|
||||
}
|
||||
return h(RedisTypeTag, {
|
||||
type: option.key,
|
||||
short: true,
|
||||
size: 'small',
|
||||
inverse: option.key === props.value,
|
||||
})
|
||||
}
|
||||
|
||||
const renderLabel = (option) => {
|
||||
const color = get(typesColor, option.key, '')
|
||||
return h('div', { style: { color, fontWeight: '450' } }, option.label)
|
||||
return h(
|
||||
'div',
|
||||
{
|
||||
style: {
|
||||
fontWeight: option.key === props.value ? 'bold' : 'normal',
|
||||
},
|
||||
},
|
||||
option.label,
|
||||
)
|
||||
}
|
||||
|
||||
const fontColor = computed(() => {
|
||||
|
|
|
@ -1,45 +1,69 @@
|
|||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { typesBgColor, typesColor, validType } from '@/consts/support_redis_type.js'
|
||||
import { typesBgColor, typesColor, typesShortName } from '@/consts/support_redis_type.js'
|
||||
import Binary from '@/components/icons/Binary.vue'
|
||||
import { toUpper } from 'lodash'
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
validator(value) {
|
||||
return validType(value)
|
||||
},
|
||||
default: 'STRING',
|
||||
},
|
||||
binaryKey: Boolean,
|
||||
size: String,
|
||||
short: Boolean,
|
||||
round: Boolean,
|
||||
inverse: Boolean,
|
||||
})
|
||||
|
||||
const fontColor = computed(() => {
|
||||
if (props.inverse) {
|
||||
return typesBgColor[props.type]
|
||||
} else {
|
||||
return typesColor[props.type]
|
||||
}
|
||||
})
|
||||
|
||||
const backgroundColor = computed(() => {
|
||||
if (props.inverse) {
|
||||
return typesColor[props.type]
|
||||
} else {
|
||||
return typesBgColor[props.type]
|
||||
}
|
||||
})
|
||||
|
||||
const label = computed(() => {
|
||||
if (props.short) {
|
||||
return typesShortName[toUpper(props.type)] || 'N'
|
||||
}
|
||||
return toUpper(props.type)
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-tag
|
||||
:class="[props.size === 'small' ? 'redis-type-tag-small' : 'redis-type-tag']"
|
||||
:class="{
|
||||
'redis-type-tag-normal': !props.short && props.size !== 'small',
|
||||
'redis-type-tag-small': !props.short && props.size === 'small',
|
||||
'redis-type-tag-round': props.round,
|
||||
}"
|
||||
:color="{ color: backgroundColor, textColor: fontColor }"
|
||||
:size="props.size"
|
||||
bordered
|
||||
strong>
|
||||
{{ props.type }}
|
||||
<b>{{ label }}</b>
|
||||
<template #icon>
|
||||
<n-icon v-if="binaryKey" :component="Binary" size="18" />
|
||||
</template>
|
||||
</n-tag>
|
||||
<!-- <div class="redis-type-tag flex-box-h" :style="{backgroundColor: backgroundColor}">{{ props.type }}</div>-->
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
.redis-type-tag {
|
||||
.redis-type-tag-round {
|
||||
border-radius: 9999px;
|
||||
}
|
||||
|
||||
.redis-type-tag-normal {
|
||||
padding: 0 12px;
|
||||
}
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ const renderTypeLabel = (option) => {
|
|||
default: () => [
|
||||
h('div', {
|
||||
style: {
|
||||
borderRadius: '50%',
|
||||
borderRadius: '9999px',
|
||||
backgroundColor: typesColor[option.value],
|
||||
width: '13px',
|
||||
height: '13px',
|
||||
|
|
|
@ -3,8 +3,8 @@ import { useThemeVars } from 'naive-ui'
|
|||
import BrowserTree from './BrowserTree.vue'
|
||||
import IconButton from '@/components/common/IconButton.vue'
|
||||
import useTabStore from 'stores/tab.js'
|
||||
import { computed, nextTick, onMounted, reactive, ref, unref, watch } from 'vue'
|
||||
import { find, get, map } from 'lodash'
|
||||
import { computed, nextTick, onMounted, reactive, ref, unref } from 'vue'
|
||||
import { find, map } from 'lodash'
|
||||
import Refresh from '@/components/icons/Refresh.vue'
|
||||
import useDialogStore from 'stores/dialog.js'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
|
@ -24,6 +24,16 @@ import ListCheckbox from '@/components/icons/ListCheckbox.vue'
|
|||
import Close from '@/components/icons/Close.vue'
|
||||
import More from '@/components/icons/More.vue'
|
||||
|
||||
const props = defineProps({
|
||||
server: String,
|
||||
db: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
})
|
||||
|
||||
const emit = defineEmits(['update:db'])
|
||||
|
||||
const themeVars = useThemeVars()
|
||||
const i18n = useI18n()
|
||||
const dialogStore = useDialogStore()
|
||||
|
@ -32,21 +42,16 @@ const tabStore = useTabStore()
|
|||
const browserStore = useBrowserStore()
|
||||
const connectionStore = useConnectionStore()
|
||||
const render = useRender()
|
||||
const currentName = computed(() => get(tabStore.currentTab, 'name', ''))
|
||||
const browserTreeRef = ref(null)
|
||||
const loading = ref(false)
|
||||
const fullyLoaded = ref(false)
|
||||
const inCheckState = ref(false)
|
||||
const checkedCount = ref(0)
|
||||
|
||||
const selectedDB = computed(() => {
|
||||
return browserStore.selectedDatabases[currentName.value] || 0
|
||||
})
|
||||
|
||||
const dbSelectOptions = computed(() => {
|
||||
const dblist = browserStore.getDBList(currentName.value)
|
||||
const dblist = browserStore.getDBList(props.server)
|
||||
return map(dblist, (db) => {
|
||||
if (selectedDB.value === db.db) {
|
||||
if (props.db === db.db) {
|
||||
return {
|
||||
value: db.db,
|
||||
label: `db${db.db} (${db.keys}/${db.maxKeys})`,
|
||||
|
@ -71,7 +76,7 @@ const moreOptions = computed(() => {
|
|||
})
|
||||
|
||||
const loadProgress = computed(() => {
|
||||
const db = browserStore.getDatabase(currentName.value, selectedDB.value)
|
||||
const db = browserStore.getDatabase(props.server, props.db)
|
||||
if (db.maxKeys <= 0) {
|
||||
return 100
|
||||
}
|
||||
|
@ -79,29 +84,29 @@ const loadProgress = computed(() => {
|
|||
})
|
||||
|
||||
const checkedTip = computed(() => {
|
||||
const dblist = browserStore.getDBList(currentName.value)
|
||||
const db = find(dblist, { db: selectedDB.value })
|
||||
const dblist = browserStore.getDBList(props.server)
|
||||
const db = find(dblist, { db: props.db })
|
||||
return `${checkedCount.value} / ${db.maxKeys}`
|
||||
})
|
||||
|
||||
const onReload = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
tabStore.setSelectedKeys(currentName.value)
|
||||
const db = selectedDB.value
|
||||
browserStore.closeDatabase(currentName.value, db)
|
||||
browserTreeRef.value?.resetExpandKey(currentName.value, db)
|
||||
tabStore.setSelectedKeys(props.server)
|
||||
const db = props.db
|
||||
browserStore.closeDatabase(props.server, db)
|
||||
browserTreeRef.value?.resetExpandKey(props.server, db)
|
||||
|
||||
let matchType = unref(filterForm.type)
|
||||
if (!types.hasOwnProperty(matchType)) {
|
||||
matchType = ''
|
||||
}
|
||||
browserStore.setKeyFilter(currentName.value, {
|
||||
browserStore.setKeyFilter(props.server, {
|
||||
type: matchType,
|
||||
pattern: unref(filterForm.pattern),
|
||||
})
|
||||
await browserStore.openDatabase(currentName.value, db)
|
||||
fullyLoaded.value = await browserStore.loadMoreKeys(currentName.value, db)
|
||||
await browserStore.openDatabase(props.server, db)
|
||||
fullyLoaded.value = await browserStore.loadMoreKeys(props.server, db)
|
||||
// $message.success(i18n.t('dialogue.reload_succ'))
|
||||
} catch (e) {
|
||||
console.warn(e)
|
||||
|
@ -111,13 +116,13 @@ const onReload = async () => {
|
|||
}
|
||||
|
||||
const onAddKey = () => {
|
||||
dialogStore.openNewKeyDialog('', currentName.value, selectedDB.value)
|
||||
dialogStore.openNewKeyDialog('', props.server, props.db)
|
||||
}
|
||||
|
||||
const onLoadMore = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
fullyLoaded.value = await browserStore.loadMoreKeys(currentName.value, selectedDB.value)
|
||||
fullyLoaded.value = await browserStore.loadMoreKeys(props.server, props.db)
|
||||
} catch (e) {
|
||||
$message.error(e.message)
|
||||
} finally {
|
||||
|
@ -128,7 +133,7 @@ const onLoadMore = async () => {
|
|||
const onLoadAll = async () => {
|
||||
try {
|
||||
loading.value = true
|
||||
await browserStore.loadAllKeys(currentName.value, selectedDB.value)
|
||||
await browserStore.loadAllKeys(props.server, props.db)
|
||||
fullyLoaded.value = true
|
||||
} catch (e) {
|
||||
$message.error(e.message)
|
||||
|
@ -142,15 +147,31 @@ const onDeleteChecked = () => {
|
|||
}
|
||||
|
||||
const onFlush = () => {
|
||||
dialogStore.openFlushDBDialog(currentName.value, selectedDB.value)
|
||||
dialogStore.openFlushDBDialog(props.server, props.db)
|
||||
}
|
||||
|
||||
const onDisconnect = () => {
|
||||
browserStore.closeConnection(currentName.value)
|
||||
browserStore.closeConnection(props.server)
|
||||
}
|
||||
|
||||
const handleSelectDB = async (db, prevDB) => {
|
||||
// watch 'browserStore.openedDB[currentName.value]' instead
|
||||
const handleSelectDB = async (db) => {
|
||||
try {
|
||||
loading.value = true
|
||||
browserStore.closeDatabase(props.server, props.db)
|
||||
browserStore.setKeyFilter(props.server, {})
|
||||
await browserStore.openDatabase(props.server, db)
|
||||
// browserTreeRef.value?.resetExpandKey(props.server, db)
|
||||
fullyLoaded.value = await browserStore.loadMoreKeys(props.server, db)
|
||||
browserTreeRef.value?.refreshTree()
|
||||
|
||||
nextTick().then(() => connectionStore.saveLastDB(props.server, db))
|
||||
} catch (e) {
|
||||
$message.error(e.message)
|
||||
} finally {
|
||||
loading.value = false
|
||||
// emit('update:db', db)
|
||||
// tabStore.switchTab()
|
||||
}
|
||||
}
|
||||
|
||||
const filterForm = reactive({
|
||||
|
@ -183,30 +204,30 @@ const onSelectOptions = (select) => {
|
|||
}
|
||||
}
|
||||
|
||||
watch(
|
||||
() => browserStore.openedDB[currentName.value],
|
||||
async (db, prevDB) => {
|
||||
if (db === undefined) {
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
browserStore.closeDatabase(currentName.value, prevDB)
|
||||
browserStore.setKeyFilter(currentName.value, {})
|
||||
await browserStore.openDatabase(currentName.value, db)
|
||||
// browserTreeRef.value?.resetExpandKey(currentName.value, db)
|
||||
fullyLoaded.value = await browserStore.loadMoreKeys(currentName.value, db)
|
||||
browserTreeRef.value?.refreshTree()
|
||||
|
||||
nextTick().then(() => connectionStore.saveLastDB(currentName.value, db))
|
||||
} catch (e) {
|
||||
$message.error(e.message)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
},
|
||||
)
|
||||
// watch(
|
||||
// () => props.db,
|
||||
// async (db, prevDB) => {
|
||||
// if (db === undefined) {
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// try {
|
||||
// loading.value = true
|
||||
// browserStore.closeDatabase(props.server, prevDB)
|
||||
// browserStore.setKeyFilter(props.server, {})
|
||||
// await browserStore.openDatabase(props.server, db)
|
||||
// // browserTreeRef.value?.resetExpandKey(props.server, db)
|
||||
// fullyLoaded.value = await browserStore.loadMoreKeys(props.server, db)
|
||||
// browserTreeRef.value?.refreshTree()
|
||||
//
|
||||
// nextTick().then(() => connectionStore.saveLastDB(props.server, db))
|
||||
// } catch (e) {
|
||||
// $message.error(e.message)
|
||||
// } finally {
|
||||
// loading.value = false
|
||||
// }
|
||||
// },
|
||||
// )
|
||||
|
||||
onMounted(() => onReload())
|
||||
// forbid dynamic switch key view due to performance issues
|
||||
|
@ -271,11 +292,11 @@ onMounted(() => onReload())
|
|||
ref="browserTreeRef"
|
||||
v-model:checked-count="checkedCount"
|
||||
:check-mode="inCheckState"
|
||||
:db="browserStore.openedDB[currentName]"
|
||||
:db="props.db"
|
||||
:full-loaded="fullyLoaded"
|
||||
:loading="loading && loadProgress <= 0"
|
||||
:pattern="filterForm.filter"
|
||||
:server="currentName" />
|
||||
:server="props.server" />
|
||||
<!-- bottom function bar -->
|
||||
<div class="nav-pane-bottom flex-box-v">
|
||||
<!-- <switch-button-->
|
||||
|
@ -288,7 +309,7 @@ onMounted(() => onReload())
|
|||
<transition mode="out-in" name="fade">
|
||||
<div v-if="!inCheckState" class="flex-box-h nav-pane-func">
|
||||
<n-select
|
||||
v-model:value="browserStore.openedDB[currentName]"
|
||||
:value="props.db"
|
||||
:consistent-menu-width="false"
|
||||
:filter="(pattern, option) => option.value.toString() === pattern"
|
||||
:options="dbSelectOptions"
|
||||
|
@ -372,16 +393,6 @@ onMounted(() => onReload())
|
|||
border-color: #0000;
|
||||
}
|
||||
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.nav-pane-top {
|
||||
//@include bottom-shadow(0.1);
|
||||
color: v-bind('themeVars.iconColor');
|
||||
|
|
|
@ -5,7 +5,7 @@ import { NIcon, NSpace, useThemeVars } from 'naive-ui'
|
|||
import Key from '@/components/icons/Key.vue'
|
||||
import Binary from '@/components/icons/Binary.vue'
|
||||
import Database from '@/components/icons/Database.vue'
|
||||
import { filter, find, get, includes, indexOf, isEmpty, map, remove, size, startsWith } from 'lodash'
|
||||
import { filter, find, get, includes, indexOf, isEmpty, map, remove, size, startsWith, toUpper } from 'lodash'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import Refresh from '@/components/icons/Refresh.vue'
|
||||
import CopyLink from '@/components/icons/CopyLink.vue'
|
||||
|
@ -23,6 +23,7 @@ import LoadList from '@/components/icons/LoadList.vue'
|
|||
import LoadAll from '@/components/icons/LoadAll.vue'
|
||||
import useBrowserStore from 'stores/browser.js'
|
||||
import { useRender } from '@/utils/render.js'
|
||||
import RedisTypeTag from '@/components/common/RedisTypeTag.vue'
|
||||
|
||||
const props = defineProps({
|
||||
server: String,
|
||||
|
@ -364,6 +365,14 @@ const renderPrefix = ({ option }) => {
|
|||
},
|
||||
)
|
||||
case ConnectionType.RedisValue:
|
||||
if (option.redisType == null || option.redisType === 'loading') {
|
||||
browserStore.loadKeyType({
|
||||
server: props.server,
|
||||
db: option.db,
|
||||
key: option.redisKey,
|
||||
keyCode: option.redisKeyCode,
|
||||
})
|
||||
// in loading
|
||||
return h(
|
||||
NIcon,
|
||||
{ size: 20 },
|
||||
|
@ -372,6 +381,13 @@ const renderPrefix = ({ option }) => {
|
|||
},
|
||||
)
|
||||
}
|
||||
return h(RedisTypeTag, {
|
||||
type: toUpper(option.redisType),
|
||||
short: true,
|
||||
size: 'small',
|
||||
inverse: includes(selectedKeys.value, option.key),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// render tree item label
|
||||
|
|
|
@ -11,6 +11,15 @@ export const types = {
|
|||
STREAM: 'STREAM',
|
||||
}
|
||||
|
||||
export const typesShortName = {
|
||||
STRING: 'S',
|
||||
HASH: 'H',
|
||||
LIST: 'L',
|
||||
SET: 'S',
|
||||
ZSET: 'Z',
|
||||
STREAM: 'X',
|
||||
}
|
||||
|
||||
/**
|
||||
* mark color for redis types
|
||||
* @enum {string}
|
||||
|
|
|
@ -30,6 +30,7 @@ import {
|
|||
GetCmdHistory,
|
||||
GetKeyDetail,
|
||||
GetKeySummary,
|
||||
GetKeyType,
|
||||
GetSlowLogs,
|
||||
LoadAllKeys,
|
||||
LoadNextKeys,
|
||||
|
@ -72,6 +73,7 @@ const useBrowserStore = defineStore('browser', {
|
|||
* @property {boolean} [opened] - redis db is opened, type == ConnectionType.RedisDB only
|
||||
* @property {boolean} [expanded] - current node is expanded
|
||||
* @property {DatabaseItem[]} [children]
|
||||
* @property {string} [redisType] - redis type name, 'loading' indicate that is in loading progress
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -339,6 +341,7 @@ const useBrowserStore = defineStore('browser', {
|
|||
|
||||
selDB.opened = true
|
||||
selDB.maxKeys = maxKeys
|
||||
this.openedDB[server] = db
|
||||
set(this.loadingState, 'fullLoaded', end)
|
||||
if (isEmpty(keys)) {
|
||||
selDB.children = []
|
||||
|
@ -465,6 +468,29 @@ const useBrowserStore = defineStore('browser', {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* load key type
|
||||
* @param {string} server
|
||||
* @param {number} db
|
||||
* @param {string} key
|
||||
* @param {number[]} keyCode
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
async loadKeyType({ server, db, key, keyCode }) {
|
||||
try {
|
||||
const nodeMap = this._getNodeMap(server, db)
|
||||
const node = nodeMap.get(`${ConnectionType.RedisValue}/${key}`)
|
||||
if (node == null || node.redisType != null) {
|
||||
return
|
||||
}
|
||||
node.redisType = 'loading'
|
||||
const { data } = await GetKeyType({ server, db, key: keyCode || key })
|
||||
const { type } = data || {}
|
||||
node.redisType = type
|
||||
} finally {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* reload key
|
||||
* @param {string} server
|
||||
|
@ -752,6 +778,7 @@ const useBrowserStore = defineStore('browser', {
|
|||
keys: 0,
|
||||
redisKey: k,
|
||||
redisKeyCode: isBinaryKey ? key : undefined,
|
||||
redisKeyType: undefined,
|
||||
type: ConnectionType.RedisValue,
|
||||
isLeaf: true,
|
||||
}
|
||||
|
@ -818,6 +845,7 @@ const useBrowserStore = defineStore('browser', {
|
|||
keys: 0,
|
||||
redisKey: handlePath,
|
||||
redisKeyCode: isBinaryKey ? key : undefined,
|
||||
redisKeyType: undefined,
|
||||
type: ConnectionType.RedisValue,
|
||||
isLeaf: true,
|
||||
}
|
||||
|
|
|
@ -119,6 +119,10 @@ const useTabStore = defineStore('tab', {
|
|||
// return current
|
||||
},
|
||||
|
||||
currentTabName() {
|
||||
return get(this.tabs, [this.activatedIndex, 'name'])
|
||||
},
|
||||
|
||||
currentSelectedKeys() {
|
||||
const tab = this.currentTab()
|
||||
return get(tab, 'selectedKeys', [])
|
||||
|
|
|
@ -157,3 +157,14 @@ body {
|
|||
.n-tabs .n-tabs-nav {
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
// animations
|
||||
.fade-enter-active,
|
||||
.fade-leave-active {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue