feat: add last format and decode selection record for keys
This commit is contained in:
parent
b745b9f45d
commit
a13bf788eb
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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,
|
||||||
})
|
})
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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, '')]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue