feat: add last format and decode selection record for keys

This commit is contained in:
Lykin 2024-03-05 11:48:55 +08:00
parent b745b9f45d
commit a13bf788eb
10 changed files with 108 additions and 30 deletions

View File

@ -756,7 +756,7 @@ func (b *browserService) GetKeyDetail(param types.KeyDetailParam) (resp types.JS
var str string var str string
str, err = client.Get(ctx, key).Result() str, err = client.Get(ctx, key).Result()
data.Value = strutil.EncodeRedisKey(str) data.Value = strutil.EncodeRedisKey(str)
//data.Value, data.Decode, data.Format = strutil.ConvertTo(str, param.Decode, param.Format) //data.Value, data.Decode, data.Format = convutil.ConvertTo(str, param.Decode, param.Format, decoder)
case "list": case "list":
loadListHandle := func() ([]types.ListEntryItem, bool, bool, error) { loadListHandle := func() ([]types.ListEntryItem, bool, bool, error) {

View File

@ -13,7 +13,6 @@ import ContentValueWrapper from '@/components/content_value/ContentValueWrapper.
import ContentCli from '@/components/content_value/ContentCli.vue' import ContentCli from '@/components/content_value/ContentCli.vue'
import Monitor from '@/components/icons/Monitor.vue' import Monitor from '@/components/icons/Monitor.vue'
import ContentSlog from '@/components/content_value/ContentSlog.vue' import ContentSlog from '@/components/content_value/ContentSlog.vue'
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
import ContentMonitor from '@/components/content_value/ContentMonitor.vue' import ContentMonitor from '@/components/content_value/ContentMonitor.vue'
import { decodeRedisKey } from '@/utils/key_convert.js' import { decodeRedisKey } from '@/utils/key_convert.js'
import ContentPubsub from '@/components/content_value/ContentPubsub.vue' import ContentPubsub from '@/components/content_value/ContentPubsub.vue'
@ -58,8 +57,8 @@ const tabContent = computed(() => {
value: tab.value, value: tab.value,
size: tab.size || 0, size: tab.size || 0,
length: tab.length || 0, length: tab.length || 0,
decode: tab.decode || decodeTypes.NONE, decode: tab.decode,
format: tab.format || formatTypes.RAW, format: tab.format,
matchPattern: tab.matchPattern || '', matchPattern: tab.matchPattern || '',
end: tab.end === true, end: tab.end === true,
loading: tab.loading === true, loading: tab.loading === true,

View File

@ -174,8 +174,8 @@ const onSave = () => {
<content-editor <content-editor
:border="true" :border="true"
:content="displayValue" :content="displayValue"
:language="viewLanguage"
:key-path="viewAs.field" :key-path="viewAs.field"
:language="viewLanguage"
class="flex-item-expand" class="flex-item-expand"
@input="onInput" @input="onInput"
@reset="onInput" @reset="onInput"

View File

@ -41,14 +41,8 @@ const props = defineProps({
}, },
size: Number, size: Number,
length: Number, length: Number,
format: { format: String,
type: String, decode: String,
default: formatTypes.RAW,
},
decode: {
type: String,
default: decodeTypes.NONE,
},
end: Boolean, end: Boolean,
loading: Boolean, loading: Boolean,
}) })

View File

@ -150,8 +150,8 @@ defineExpose({
:content="displayValue" :content="displayValue"
:loading="props.loading" :loading="props.loading"
:offset-key="props.keyPath" :offset-key="props.keyPath"
keep-offset
class="flex-item-expand" class="flex-item-expand"
keep-offset
language="json" language="json"
style="height: 100%" style="height: 100%"
@input="onInput" @input="onInput"

View File

@ -27,6 +27,12 @@ const props = defineProps({
default: -1, default: -1,
}, },
value: [String, Array], value: [String, Array],
format: {
type: String,
},
decode: {
type: String,
},
size: Number, size: Number,
length: Number, length: Number,
loading: Boolean, loading: Boolean,
@ -100,12 +106,13 @@ const onFormatChanged = async (decode = '', format = '') => {
format: retFormat, format: retFormat,
} = await browserStore.convertValue({ } = await browserStore.convertValue({
value: props.value, value: props.value,
decode, decode: decode || props.decode,
format, format: format || props.format,
}) })
editingContent.value = viewAs.value = value editingContent.value = viewAs.value = value
viewAs.decode = decode || retDecode viewAs.decode = decode || retDecode
viewAs.format = format || retFormat viewAs.format = format || retFormat
browserStore.setSelectedFormat(props.name, props.keyPath, props.db, viewAs.format, viewAs.decode)
} finally { } finally {
converting.value = false converting.value = false
} }
@ -205,8 +212,8 @@ defineExpose({
:language="viewLanguage" :language="viewLanguage"
:loading="props.loading" :loading="props.loading"
:offset-key="props.keyPath" :offset-key="props.keyPath"
keep-offset
class="flex-item-expand" class="flex-item-expand"
keep-offset
style="height: 100%" style="height: 100%"
@input="onInput" @input="onInput"
@reset="onInput" @reset="onInput"

View File

@ -11,7 +11,6 @@ import useBrowserStore from 'stores/browser.js'
import { computed, onMounted, ref, watch } from 'vue' import { computed, onMounted, ref, watch } from 'vue'
import { isEmpty } from 'lodash' import { isEmpty } from 'lodash'
import useDialogStore from 'stores/dialog.js' import useDialogStore from 'stores/dialog.js'
import { decodeTypes, formatTypes } from '@/consts/value_view_type.js'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
import ContentToolbar from '@/components/content_value/ContentToolbar.vue' import ContentToolbar from '@/components/content_value/ContentToolbar.vue'
import ContentValueJson from '@/components/content_value/ContentValueJson.vue' import ContentValueJson from '@/components/content_value/ContentValueJson.vue'
@ -86,15 +85,15 @@ const loadData = async (reset, full, selMatch) => {
if (!!props.blank) { if (!!props.blank) {
return return
} }
const { name, db, matchPattern, decode, format } = data.value const { name, db, matchPattern } = data.value
reset = reset === true reset = reset === true
await browserStore.loadKeyDetail({ await browserStore.loadKeyDetail({
server: name, server: name,
db: db, db: db,
key: keyName.value, key: keyName.value,
matchPattern: selMatch === undefined ? matchPattern : selMatch, matchPattern: selMatch === undefined ? matchPattern : selMatch,
decode: reset ? decodeTypes.NONE : decode, decode: '',
format: reset ? formatTypes.RAW : format, format: '',
reset, reset,
full: full === true, full: full === true,
}) })
@ -111,12 +110,15 @@ const loadData = async (reset, full, selMatch) => {
const onReload = async (selDecode, selFormat) => { const onReload = async (selDecode, selFormat) => {
try { try {
const { name, db, keyCode, keyPath, decode, format, matchPattern } = data.value const { name, db, keyCode, keyPath, decode, format, matchPattern } = data.value
const targetFormat = selFormat || format
const targetDecode = selDecode || decode
browserStore.setSelectedFormat(name, keyPath, db, targetFormat, targetDecode)
await browserStore.reloadKey({ await browserStore.reloadKey({
server: name, server: name,
db, db,
key: keyCode || keyPath, key: keyCode || keyPath,
decode: selDecode || decode, decode: targetDecode,
format: selFormat || format, format: targetFormat,
matchPattern, matchPattern,
}) })
} finally { } finally {

View File

@ -1,4 +1,4 @@
import { initial, isEmpty, join, last, mapValues, size, slice, sortBy, split, toUpper } from 'lodash' import { get, initial, isEmpty, join, last, mapValues, size, slice, sortBy, split, toUpper } from 'lodash'
import useConnectionStore from 'stores/connections.js' import useConnectionStore from 'stores/connections.js'
import { ConnectionType } from '@/consts/connection_type.js' import { ConnectionType } from '@/consts/connection_type.js'
import { RedisDatabaseItem } from '@/objects/redisDatabaseItem.js' import { RedisDatabaseItem } from '@/objects/redisDatabaseItem.js'
@ -49,6 +49,8 @@ export class RedisServerState {
this.loadingState = loadingState this.loadingState = loadingState
this.viewType = viewType this.viewType = viewType
this.nodeMap = nodeMap this.nodeMap = nodeMap
this.decodeHistory = new Map()
this.decodeHistoryLimit = 100
this.getRoot() this.getRoot()
const connStore = useConnectionStore() const connStore = useConnectionStore()
@ -457,4 +459,37 @@ export class RedisServerState {
this.patternFilter = pattern === null ? this.patternFilter : pattern this.patternFilter = pattern === null ? this.patternFilter : pattern
this.typeFilter = type === null ? this.typeFilter : type this.typeFilter = type === null ? this.typeFilter : type
} }
/**
* add manually selected decode type to history
* @param {string} key
* @param {number} db
* @param {string} format
* @param {string} decode
*/
addDecodeHistory(key, db, format = '', decode = '') {
const decodeKey = `${key}#${db}`
this.decodeHistory.delete(decodeKey)
if (isEmpty(format) && isEmpty(decode)) {
// reset to default, remove from history
return
}
this.decodeHistory.set(decodeKey, [format, decode])
while (this.decodeHistory.size > this.decodeHistoryLimit) {
const k = this.decodeHistory.keys().next().value
this.decodeHistory.delete(k)
}
}
/**
* get manually selected decode type from history
* @param {string|number[]} key
* @param {number} db
* @return {[]}
*/
getDecodeHistory(key, db) {
const h = this.decodeHistory.get(`${nativeRedisKey(key)}#${db}`) || []
return [get(h, 0, ''), get(h, 1, '')]
}
} }

View File

@ -422,7 +422,7 @@ const useBrowserStore = defineStore('browser', {
clearValue, clearValue,
}) })
} catch (e) { } catch (e) {
$message.error('') $message.error(e.message || 'unknown error')
} finally { } finally {
} }
}, },
@ -495,14 +495,19 @@ const useBrowserStore = defineStore('browser', {
*/ */
async loadKeyDetail({ server, db, key, format, decode, matchPattern, reset, full }) { async loadKeyDetail({ server, db, key, format, decode, matchPattern, reset, full }) {
const tab = useTabStore() const tab = useTabStore()
const serverInst = this.servers[server]
if (serverInst == null) {
return
}
try { try {
tab.updateLoading({ server, db, loading: true }) tab.updateLoading({ server, db, loading: true })
const [storeFormat, storeDecode] = serverInst.getDecodeHistory(key, db)
const { data, success, msg } = await GetKeyDetail({ const { data, success, msg } = await GetKeyDetail({
server, server,
db, db,
key, key,
format, format: isEmpty(format) ? storeFormat : format,
decode, decode: isEmpty(decode) ? storeDecode : decode,
matchPattern, matchPattern,
full: full === true, full: full === true,
reset, reset,
@ -523,8 +528,8 @@ const useBrowserStore = defineStore('browser', {
db, db,
key: nativeRedisKey(key), key: nativeRedisKey(key),
value, value,
decode: retDecode, decode: retDecode || storeDecode,
format: retFormat, format: retFormat || storeFormat,
reset: retReset, reset: retReset,
matchPattern: retMatch || '', matchPattern: retMatch || '',
end, end,
@ -1935,6 +1940,22 @@ const useBrowserStore = defineStore('browser', {
serverInst.setFilter({ pattern, type }) serverInst.setFilter({ pattern, type })
} }
}, },
/**
*
* @param {string} server
* @param {string} key
* @param {number} db
* @param {string} format
* @param {string} decode
*/
setSelectedFormat(server, key, db, format, decode) {
const serverInst = this.servers[server]
if (serverInst == null) {
return
}
serverInst.addDecodeHistory(key, db, format, decode)
},
}, },
}) })

View File

@ -145,9 +145,25 @@ const useTabStore = defineStore('tab', {
* @param {number} [length] * @param {number} [length]
* @param {string} [matchPattern] * @param {string} [matchPattern]
* @param {boolean} [clearValue] * @param {boolean} [clearValue]
* @param {string} format
* @param {string} decode
* @param {*} [value] * @param {*} [value]
*/ */
upsertTab({ subTab, server, db, type, ttl, key, keyCode, size, length, matchPattern = '', clearValue }) { upsertTab({
subTab,
server,
db,
type,
ttl,
key,
keyCode,
size,
length,
matchPattern = '',
clearValue,
format = '',
decode = '',
}) {
let tabIndex = findIndex(this.tabList, { name: server }) let tabIndex = findIndex(this.tabList, { name: server })
if (tabIndex === -1) { if (tabIndex === -1) {
const tabItem = new TabItem({ const tabItem = new TabItem({
@ -164,6 +180,8 @@ const useTabStore = defineStore('tab', {
length, length,
matchPattern, matchPattern,
value: undefined, value: undefined,
format,
decode,
}) })
this.tabList.push(tabItem) this.tabList.push(tabItem)
tabIndex = this.tabList.length - 1 tabIndex = this.tabList.length - 1
@ -182,6 +200,8 @@ const useTabStore = defineStore('tab', {
tab.size = size tab.size = size
tab.length = length tab.length = length
tab.matchPattern = matchPattern tab.matchPattern = matchPattern
tab.format = format
tab.decode = decode
if (clearValue === true) { if (clearValue === true) {
tab.value = undefined tab.value = undefined
} }