refactor: optimized refresh logic after update fields for hash type
This commit is contained in:
parent
d88fd35e9d
commit
80e659e03a
|
@ -1081,7 +1081,7 @@ func (b *browserService) SetKeyValue(param types.SetKeyParam) (resp types.JSResp
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetHashValue set hash field
|
// SetHashValue update hash field
|
||||||
func (b *browserService) SetHashValue(param types.SetHashParam) (resp types.JSResp) {
|
func (b *browserService) SetHashValue(param types.SetHashParam) (resp types.JSResp) {
|
||||||
item, err := b.getRedisClient(param.Server, param.DB)
|
item, err := b.getRedisClient(param.Server, param.DB)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -1092,36 +1092,64 @@ func (b *browserService) SetHashValue(param types.SetHashParam) (resp types.JSRe
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(param.Key)
|
key := strutil.DecodeRedisKey(param.Key)
|
||||||
str := strutil.DecodeRedisKey(param.Value)
|
str := strutil.DecodeRedisKey(param.Value)
|
||||||
var saveStr string
|
var saveStr, displayStr string
|
||||||
if saveStr, err = strutil.SaveAs(str, param.Format, param.Decode); err != nil {
|
if saveStr, err = strutil.SaveAs(str, param.Format, param.Decode); err != nil {
|
||||||
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
|
resp.Msg = fmt.Sprintf(`save to type "%s" fail: %s`, param.Format, err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var removedField []string
|
displayStr, _, _ = strutil.ConvertTo(saveStr, param.RetDecode, param.RetFormat)
|
||||||
updatedField := map[string]any{}
|
var updated, added, removed []types.HashEntryItem
|
||||||
replacedField := map[string]any{}
|
var replaced []types.HashReplaceItem
|
||||||
if len(param.Field) <= 0 {
|
var affect int64
|
||||||
// old filed is empty, add new field
|
if len(param.NewField) <= 0 {
|
||||||
_, err = client.HSet(ctx, key, param.NewField, saveStr).Result()
|
|
||||||
updatedField[param.NewField] = saveStr
|
|
||||||
} else if len(param.NewField) <= 0 {
|
|
||||||
// new field is empty, delete old field
|
// new field is empty, delete old field
|
||||||
_, err = client.HDel(ctx, key, param.Field).Result()
|
_, err = client.HDel(ctx, key, param.Field).Result()
|
||||||
removedField = append(removedField, param.Field)
|
removed = append(removed, types.HashEntryItem{
|
||||||
} else if param.Field == param.NewField {
|
Key: param.Field,
|
||||||
// update field value
|
})
|
||||||
_, err = client.HSet(ctx, key, param.Field, saveStr).Result()
|
} else if len(param.Field) <= 0 || param.Field == param.NewField {
|
||||||
updatedField[param.NewField] = saveStr
|
affect, err = client.HSet(ctx, key, param.NewField, saveStr).Result()
|
||||||
|
if affect <= 0 {
|
||||||
|
// update field value
|
||||||
|
updated = append(updated, types.HashEntryItem{
|
||||||
|
Key: param.NewField,
|
||||||
|
Value: saveStr,
|
||||||
|
DisplayValue: displayStr,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// add new field
|
||||||
|
added = append(added, types.HashEntryItem{
|
||||||
|
Key: param.NewField,
|
||||||
|
Value: saveStr,
|
||||||
|
DisplayValue: displayStr,
|
||||||
|
})
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// remove old field and add new field
|
// remove old field and add new field
|
||||||
if _, err = client.HDel(ctx, key, param.Field).Result(); err != nil {
|
if _, err = client.HDel(ctx, key, param.Field).Result(); err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_, err = client.HSet(ctx, key, param.NewField, saveStr).Result()
|
affect, err = client.HSet(ctx, key, param.NewField, saveStr).Result()
|
||||||
removedField = append(removedField, param.Field)
|
if affect <= 0 {
|
||||||
updatedField[param.NewField] = saveStr
|
// no new filed added, just replace exists item
|
||||||
replacedField[param.Field] = param.NewField
|
removed = append(removed, types.HashEntryItem{
|
||||||
|
Key: param.Field,
|
||||||
|
})
|
||||||
|
updated = append(updated, types.HashEntryItem{
|
||||||
|
Key: param.NewField,
|
||||||
|
Value: saveStr,
|
||||||
|
DisplayValue: displayStr,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
// add new field
|
||||||
|
replaced = append(replaced, types.HashReplaceItem{
|
||||||
|
Key: param.Field,
|
||||||
|
NewKey: param.NewField,
|
||||||
|
Value: saveStr,
|
||||||
|
DisplayValue: displayStr,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
|
@ -1129,10 +1157,16 @@ func (b *browserService) SetHashValue(param types.SetHashParam) (resp types.JSRe
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
resp.Data = struct {
|
||||||
"removed": removedField,
|
Added []types.HashEntryItem `json:"added,omitempty"`
|
||||||
"updated": updatedField,
|
Removed []types.HashEntryItem `json:"removed,omitempty"`
|
||||||
"replaced": replacedField,
|
Updated []types.HashEntryItem `json:"updated,omitempty"`
|
||||||
|
Replaced []types.HashReplaceItem `json:"replaced,omitempty"`
|
||||||
|
}{
|
||||||
|
Added: added,
|
||||||
|
Removed: removed,
|
||||||
|
Updated: updated,
|
||||||
|
Replaced: replaced,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1314,8 +1348,7 @@ func (b *browserService) SetSetItem(server string, db int, k any, remove bool, m
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
if affected, _ = client.SRem(ctx, key, member).Result(); affected > 0 {
|
if affected, _ = client.SRem(ctx, key, member).Result(); affected > 0 {
|
||||||
removed = append(removed, types.SetEntryItem{
|
removed = append(removed, types.SetEntryItem{
|
||||||
Value: member,
|
Value: member,
|
||||||
DisplayValue: "", // TODO: convert to display value
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,14 +60,16 @@ type SetListParam struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetHashParam struct {
|
type SetHashParam struct {
|
||||||
Server string `json:"server"`
|
Server string `json:"server"`
|
||||||
DB int `json:"db"`
|
DB int `json:"db"`
|
||||||
Key any `json:"key"`
|
Key any `json:"key"`
|
||||||
Field string `json:"field,omitempty"`
|
Field string `json:"field,omitempty"`
|
||||||
NewField string `json:"newField,omitempty"`
|
NewField string `json:"newField,omitempty"`
|
||||||
Value any `json:"value"`
|
Value any `json:"value"`
|
||||||
Format string `json:"format,omitempty"`
|
Format string `json:"format,omitempty"`
|
||||||
Decode string `json:"decode,omitempty"`
|
Decode string `json:"decode,omitempty"`
|
||||||
|
RetFormat string `json:"retFormat,omitempty"`
|
||||||
|
RetDecode string `json:"retDecode,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SetSetParam struct {
|
type SetSetParam struct {
|
||||||
|
|
|
@ -5,12 +5,25 @@ type ListEntryItem struct {
|
||||||
DisplayValue string `json:"dv,omitempty"`
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ListReplaceItem struct {
|
||||||
|
Index int64 `json:"index"`
|
||||||
|
Value any `json:"v"`
|
||||||
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type HashEntryItem struct {
|
type HashEntryItem struct {
|
||||||
Key string `json:"k"`
|
Key string `json:"k"`
|
||||||
Value any `json:"v"`
|
Value any `json:"v"`
|
||||||
DisplayValue string `json:"dv,omitempty"`
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type HashReplaceItem struct {
|
||||||
|
Key any `json:"k"`
|
||||||
|
NewKey any `json:"nk"`
|
||||||
|
Value any `json:"v"`
|
||||||
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type SetEntryItem struct {
|
type SetEntryItem struct {
|
||||||
Value any `json:"v"`
|
Value any `json:"v"`
|
||||||
DisplayValue string `json:"dv,omitempty"`
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
|
@ -22,6 +35,13 @@ type ZSetEntryItem struct {
|
||||||
DisplayValue string `json:"dv,omitempty"`
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ZSetReplaceItem struct {
|
||||||
|
Score float64 `json:"s"`
|
||||||
|
Value string `json:"v"`
|
||||||
|
NewValue string `json:"nv"`
|
||||||
|
DisplayValue string `json:"dv,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type StreamEntryItem struct {
|
type StreamEntryItem struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
Value map[string]any `json:"v"`
|
Value map[string]any `json:"v"`
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func containsBinary(str string) bool {
|
func containsBinary(str string) bool {
|
||||||
|
//buf := []byte(str)
|
||||||
//size := 0
|
//size := 0
|
||||||
//for start := 0; start < len(buf); start += size {
|
//for start := 0; start < len(buf); start += size {
|
||||||
// var r rune
|
// var r rune
|
||||||
|
@ -14,9 +15,25 @@ func containsBinary(str string) bool {
|
||||||
//}
|
//}
|
||||||
rs := []rune(str)
|
rs := []rune(str)
|
||||||
for _, r := range rs {
|
for _, r := range rs {
|
||||||
if !unicode.IsPrint(r) && r != '\n' {
|
if !unicode.IsPrint(r) && !unicode.IsSpace(r) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isSameChar(str string) bool {
|
||||||
|
if len(str) <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
rs := []rune(str)
|
||||||
|
first := rs[0]
|
||||||
|
for _, r := range rs {
|
||||||
|
if r != first {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -109,9 +109,11 @@ func autoDecode(str string) (value, resultDecode string) {
|
||||||
// pure digit content may incorrect regard as some encoded type, skip decode
|
// pure digit content may incorrect regard as some encoded type, skip decode
|
||||||
if match, _ := regexp.MatchString(`^\d+$`, str); !match {
|
if match, _ := regexp.MatchString(`^\d+$`, str); !match {
|
||||||
var ok bool
|
var ok bool
|
||||||
if value, ok = decodeBase64(str); ok {
|
if len(str)%4 == 0 && !isSameChar(str) {
|
||||||
resultDecode = types.DECODE_BASE64
|
if value, ok = decodeBase64(str); ok {
|
||||||
return
|
resultDecode = types.DECODE_BASE64
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if value, ok = decodeGZip(str); ok {
|
if value, ok = decodeGZip(str); ok {
|
||||||
|
|
|
@ -158,7 +158,7 @@ const saveEdit = async (field, value, decode, format) => {
|
||||||
throw new Error('row not exists')
|
throw new Error('row not exists')
|
||||||
}
|
}
|
||||||
|
|
||||||
const { updated, success, msg } = await browserStore.setHash({
|
const { success, msg } = await browserStore.setHash({
|
||||||
server: props.name,
|
server: props.name,
|
||||||
db: props.db,
|
db: props.db,
|
||||||
key: keyName.value,
|
key: keyName.value,
|
||||||
|
@ -167,16 +167,11 @@ const saveEdit = async (field, value, decode, format) => {
|
||||||
value,
|
value,
|
||||||
decode,
|
decode,
|
||||||
format,
|
format,
|
||||||
|
retDecode: props.decode,
|
||||||
|
retFormat: props.format,
|
||||||
|
index: [currentEditRow.no - 1],
|
||||||
})
|
})
|
||||||
if (success) {
|
if (success) {
|
||||||
row.k = field
|
|
||||||
row.v = updated[row.k] || ''
|
|
||||||
const { value: displayVal } = await browserStore.convertValue({
|
|
||||||
value: row.v,
|
|
||||||
decode: props.decode,
|
|
||||||
format: props.format,
|
|
||||||
})
|
|
||||||
row.dv = displayVal
|
|
||||||
$message.success(i18n.t('dialogue.save_value_succ'))
|
$message.success(i18n.t('dialogue.save_value_succ'))
|
||||||
} else {
|
} else {
|
||||||
$message.error(msg)
|
$message.error(msg)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import {
|
||||||
isEmpty,
|
isEmpty,
|
||||||
join,
|
join,
|
||||||
last,
|
last,
|
||||||
|
map,
|
||||||
remove,
|
remove,
|
||||||
set,
|
set,
|
||||||
size,
|
size,
|
||||||
|
@ -1010,7 +1011,10 @@ const useBrowserStore = defineStore('browser', {
|
||||||
* @param {string} [value]
|
* @param {string} [value]
|
||||||
* @param {string} [decode]
|
* @param {string} [decode]
|
||||||
* @param {string} [format]
|
* @param {string} [format]
|
||||||
|
* @param {string} [retDecode]
|
||||||
|
* @param {string} [retFormat]
|
||||||
* @param {boolean} [refresh]
|
* @param {boolean} [refresh]
|
||||||
|
* @param {number} [index] index for retrieve affect entries quickly
|
||||||
* @returns {Promise<{[msg]: string, success: boolean, [updated]: {}}>}
|
* @returns {Promise<{[msg]: string, success: boolean, [updated]: {}}>}
|
||||||
*/
|
*/
|
||||||
async setHash({
|
async setHash({
|
||||||
|
@ -1022,7 +1026,9 @@ const useBrowserStore = defineStore('browser', {
|
||||||
value = '',
|
value = '',
|
||||||
decode = decodeTypes.NONE,
|
decode = decodeTypes.NONE,
|
||||||
format = formatTypes.RAW,
|
format = formatTypes.RAW,
|
||||||
refresh,
|
retDecode,
|
||||||
|
retFormat,
|
||||||
|
index,
|
||||||
}) {
|
}) {
|
||||||
try {
|
try {
|
||||||
const { data, success, msg } = await SetHashValue({
|
const { data, success, msg } = await SetHashValue({
|
||||||
|
@ -1036,15 +1042,30 @@ const useBrowserStore = defineStore('browser', {
|
||||||
format,
|
format,
|
||||||
})
|
})
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updated = {}, removed = [], replaced = {} } = data
|
/**
|
||||||
if (refresh === true) {
|
* @type {{updated: HashEntryItem[], removed: HashEntryItem[], updated: HashEntryItem[], replaced: HashReplaceItem[]}}
|
||||||
const tab = useTabStore()
|
*/
|
||||||
if (!isEmpty(removed)) {
|
const { updated = [], removed = [], added = [], replaced = [] } = data
|
||||||
tab.removeValueEntries({ server, db, key, type: 'hash', entries: removed })
|
const tab = useTabStore()
|
||||||
}
|
if (!isEmpty(removed)) {
|
||||||
if (!isEmpty(updated)) {
|
const removedKeys = map(removed, (e) => e.k)
|
||||||
tab.upsertValueEntries({ server, db, key, type: 'hash', entries: updated })
|
tab.removeValueEntries({ server, db, key, type: 'hash', entries: removedKeys })
|
||||||
}
|
}
|
||||||
|
if (!isEmpty(updated)) {
|
||||||
|
tab.updateValueEntries({ server, db, key, type: 'hash', entries: updated })
|
||||||
|
}
|
||||||
|
if (!isEmpty(added)) {
|
||||||
|
tab.insertValueEntries({ server, db, key, type: 'hash', entries: added })
|
||||||
|
}
|
||||||
|
if (!isEmpty(replaced)) {
|
||||||
|
tab.replaceValueEntries({
|
||||||
|
server,
|
||||||
|
db,
|
||||||
|
key,
|
||||||
|
type: 'hash',
|
||||||
|
entries: replaced,
|
||||||
|
index: [index],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
return { success, updated }
|
return { success, updated }
|
||||||
} else {
|
} else {
|
||||||
|
@ -1071,7 +1092,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { updated = [], added = [] } = data
|
const { updated = [], added = [] } = data
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
if (!isEmpty(updated)) {
|
if (!isEmpty(updated)) {
|
||||||
tab.replaceValueEntries({ server, db, key, type: 'hash', entries: updated })
|
tab.updateValueEntries({ server, db, key, type: 'hash', entries: updated })
|
||||||
}
|
}
|
||||||
if (!isEmpty(added)) {
|
if (!isEmpty(added)) {
|
||||||
tab.insertValueEntries({ server, db, key, type: 'hash', entries: added })
|
tab.insertValueEntries({ server, db, key, type: 'hash', entries: added })
|
||||||
|
@ -1360,7 +1381,7 @@ const useBrowserStore = defineStore('browser', {
|
||||||
tab.insertValueEntries({ server, db, key, type: 'zset', entries: added })
|
tab.insertValueEntries({ server, db, key, type: 'zset', entries: added })
|
||||||
}
|
}
|
||||||
if (!isEmpty(updated)) {
|
if (!isEmpty(updated)) {
|
||||||
tab.replaceValueEntries({ server, db, key, type: 'zset', entries: updated })
|
tab.updateValueEntries({ server, db, key, type: 'zset', entries: updated })
|
||||||
}
|
}
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { assign, find, findIndex, get, indexOf, isEmpty, pullAt, remove, set, size } from 'lodash'
|
import { assign, find, findIndex, get, includes, isEmpty, pullAt, remove, set, size } from 'lodash'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
const useTabStore = defineStore('tab', {
|
const useTabStore = defineStore('tab', {
|
||||||
|
@ -25,6 +25,62 @@ const useTabStore = defineStore('tab', {
|
||||||
* @param {boolean} [loading]
|
* @param {boolean} [loading]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} ListEntryItem
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} ListReplaceItem
|
||||||
|
* @property {number} index
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} HashEntryItem
|
||||||
|
* @property {string} k field name
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} HashReplaceItem
|
||||||
|
* @property {string|number[]} k field name
|
||||||
|
* @property {string|number[]} nk new field name
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} SetEntryItem
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} ZSetEntryItem
|
||||||
|
* @property {number} s score
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} ZSetReplaceItem
|
||||||
|
* @property {number} s score
|
||||||
|
* @property {string|number[]} v value
|
||||||
|
* @property {string|number[]} nv new value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} StreamEntryItem
|
||||||
|
* @property {string} id
|
||||||
|
* @property {Object.<string, *>} v value
|
||||||
|
* @property {string} [dv] display value
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @returns {{tabList: TabItem[], activatedTab: string, activatedIndex: number}}
|
* @returns {{tabList: TabItem[], activatedTab: string, activatedIndex: number}}
|
||||||
|
@ -177,151 +233,13 @@ const useTabStore = defineStore('tab', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* update or insert value entries
|
|
||||||
* @param {string} server
|
|
||||||
* @param {number} db
|
|
||||||
* @param {string} key
|
|
||||||
* @param {string} type
|
|
||||||
* @param {string[]|Object.<string, number>|Object.<number, string>|{k:string, v:string}[]} entries
|
|
||||||
* @param {boolean} [prepend] for list only
|
|
||||||
* @param {boolean} [reset]
|
|
||||||
* @param {boolean} [nocheck] ignore conflict checking for hash/set/zset
|
|
||||||
*/
|
|
||||||
upsertValueEntries({ server, db, key, type, entries, prepend, reset, nocheck }) {
|
|
||||||
const tab = find(this.tabList, { name: server, db, key })
|
|
||||||
if (tab == null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (type.toLowerCase()) {
|
|
||||||
case 'list': // string[] | Object.<number, string>
|
|
||||||
if (entries instanceof Array) {
|
|
||||||
// append or prepend items
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
if (prepend === true) {
|
|
||||||
tab.value = [...entries, ...tab.value]
|
|
||||||
} else {
|
|
||||||
tab.value.push(...entries)
|
|
||||||
}
|
|
||||||
tab.length += size(entries)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// replace by index
|
|
||||||
tab.value = tab.value || []
|
|
||||||
for (const idx in entries) {
|
|
||||||
set(tab.value, idx, entries[idx])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'hash': // Object.<string, string>
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = {}
|
|
||||||
tab.length = 0
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || {}
|
|
||||||
}
|
|
||||||
if (entries instanceof Array) {
|
|
||||||
// append new item
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.value.push(...entries)
|
|
||||||
}
|
|
||||||
tab.length += size(entries)
|
|
||||||
} else {
|
|
||||||
// replace item {key: value}
|
|
||||||
for (const ent in entries) {
|
|
||||||
let found = false
|
|
||||||
for (const elem of tab.value) {
|
|
||||||
if (elem.k === ent) {
|
|
||||||
elem.v = entries[elem.k]
|
|
||||||
elem.dv = ent.dv
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found && nocheck !== true) {
|
|
||||||
tab.length += 1
|
|
||||||
tab.value.push(ent)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'set': // string[] | Object.{string, string}
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
if (entries instanceof Array) {
|
|
||||||
// add items
|
|
||||||
for (const elem of entries) {
|
|
||||||
if (nocheck !== true && indexOf(tab.value, elem) === -1) {
|
|
||||||
tab.value.push(elem)
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// replace items
|
|
||||||
for (const k in entries) {
|
|
||||||
const idx = indexOf(tab.value, k)
|
|
||||||
if (idx !== -1) {
|
|
||||||
tab.value[idx] = entries[k]
|
|
||||||
} else {
|
|
||||||
tab.value.push(entries[k])
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'zset': // {value: string, score: number}
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = Object.entries(entries).map(([value, score]) => ({ value, score }))
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
for (const val in entries) {
|
|
||||||
if (nocheck !== true) {
|
|
||||||
const ent = find(tab.value, (e) => e.value === val)
|
|
||||||
if (ent != null) {
|
|
||||||
ent.score = entries[val]
|
|
||||||
} else {
|
|
||||||
tab.value.push({ value: val, score: entries[val] })
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
tab.value.push({ value: val, score: entries[val] })
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'stream': // [{id: string, value: []any}]
|
|
||||||
if (reset === true) {
|
|
||||||
tab.value = entries
|
|
||||||
} else {
|
|
||||||
tab.value = tab.value || []
|
|
||||||
tab.value = [...entries, ...tab.value]
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* insert entries
|
* insert entries
|
||||||
* @param {string} server
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
* @param {any[]} entries
|
* @param {ListEntryItem[]|HashEntryItem[]|SetEntryItem[]|ZSetEntryItem[]|StreamEntryItem[]} entries
|
||||||
* @param {boolean} [prepend] for list only
|
* @param {boolean} [prepend] for list only
|
||||||
*/
|
*/
|
||||||
insertValueEntries({ server, db, key, type, entries, prepend }) {
|
insertValueEntries({ server, db, key, type, entries, prepend }) {
|
||||||
|
@ -363,28 +281,15 @@ const useTabStore = defineStore('tab', {
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
* @param {any[]} entries
|
* @param {ListEntryItem[]|HashEntryItem[]|SetEntryItem[]|ZSetEntryItem[]|StreamEntryItem[]} entries
|
||||||
*/
|
*/
|
||||||
replaceValueEntries({ server, db, key, type, entries }) {
|
updateValueEntries({ server, db, key, type, entries }) {
|
||||||
const tab = find(this.tabList, { name: server, db, key })
|
const tab = find(this.tabList, { name: server, db, key })
|
||||||
if (tab == null) {
|
if (tab == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type.toLowerCase()) {
|
switch (type.toLowerCase()) {
|
||||||
case 'list': // {index:number, v:string, dv:[string]}[]
|
|
||||||
tab.value = tab.value || []
|
|
||||||
for (const entry of entries) {
|
|
||||||
if (size(tab.value) < entry.index) {
|
|
||||||
tab.value[entry.index] = entry
|
|
||||||
} else {
|
|
||||||
// out of range, append
|
|
||||||
tab.value.push(entry)
|
|
||||||
tab.length += 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
|
|
||||||
case 'hash': // {k:string, v:string, dv:string}[]
|
case 'hash': // {k:string, v:string, dv:string}[]
|
||||||
tab.value = tab.value || []
|
tab.value = tab.value || []
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
|
@ -423,6 +328,102 @@ const useTabStore = defineStore('tab', {
|
||||||
tab.length += 1
|
tab.length += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace entry item key or field in value
|
||||||
|
* @param {string} server
|
||||||
|
* @param {number} db
|
||||||
|
* @param {string|number[]} key
|
||||||
|
* @param {string} type
|
||||||
|
* @param {ListReplaceItem[]|HashReplaceItem[]|ZSetReplaceItem[]} entries
|
||||||
|
* @param {number[]} [index] indexes for replacement, can improve search efficiency if configured
|
||||||
|
*/
|
||||||
|
replaceValueEntries({ server, db, key, type, entries, index }) {
|
||||||
|
const tab = find(this.tabList, { name: server, db, key })
|
||||||
|
if (tab == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type.toLowerCase()) {
|
||||||
|
case 'list': // {index:number, v:string, dv:[string]}[]
|
||||||
|
tab.value = tab.value || []
|
||||||
|
for (const entry of entries) {
|
||||||
|
if (size(tab.value) < entry.index) {
|
||||||
|
tab.value[entry.index] = entry
|
||||||
|
} else {
|
||||||
|
// out of range, append
|
||||||
|
tab.value.push(entry)
|
||||||
|
tab.length += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'hash':
|
||||||
|
tab.value = tab.value || []
|
||||||
|
for (const idx of index) {
|
||||||
|
const entry = get(tab.value, idx)
|
||||||
|
if (entry != null) {
|
||||||
|
/** @type HashReplaceItem[] **/
|
||||||
|
const replaceEntry = remove(entries, (e) => e.k === entry.k)
|
||||||
|
if (!isEmpty(replaceEntry)) {
|
||||||
|
entry.k = replaceEntry[0].nk
|
||||||
|
entry.v = replaceEntry[0].v
|
||||||
|
entry.dv = replaceEntry[0].dv
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the left entries do not included in index list, try to retrieve the whole list
|
||||||
|
for (const entry of entries) {
|
||||||
|
let updated = false
|
||||||
|
for (const val of tab.value) {
|
||||||
|
if (val.k === entry.k) {
|
||||||
|
val.k = entry.nk
|
||||||
|
val.v = entry.v
|
||||||
|
val.dv = entry.dv
|
||||||
|
updated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!updated) {
|
||||||
|
// no match element, append
|
||||||
|
tab.value.push({
|
||||||
|
k: entry.nk,
|
||||||
|
v: entry.v,
|
||||||
|
dv: entry.dv,
|
||||||
|
})
|
||||||
|
tab.length += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'zset':
|
||||||
|
tab.value = tab.value || []
|
||||||
|
for (const entry of entries) {
|
||||||
|
let updated = false
|
||||||
|
for (const val of tab.value) {
|
||||||
|
if (val.v === entry.v) {
|
||||||
|
val.s = entry.s
|
||||||
|
val.v = entry.nv
|
||||||
|
val.dv = entry.dv
|
||||||
|
updated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!updated) {
|
||||||
|
// no match element, append
|
||||||
|
tab.value.push({
|
||||||
|
s: entry.s,
|
||||||
|
v: entry.nv,
|
||||||
|
dv: entry.dv,
|
||||||
|
})
|
||||||
|
tab.length += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -460,12 +461,8 @@ const useTabStore = defineStore('tab', {
|
||||||
|
|
||||||
case 'hash': // string[]
|
case 'hash': // string[]
|
||||||
tab.value = tab.value || {}
|
tab.value = tab.value || {}
|
||||||
for (const k of entries) {
|
const removedElems = remove(tab.value, (e) => includes(entries, e.k))
|
||||||
if (tab.value.hasOwnProperty(k)) {
|
tab.length -= size(removedElems)
|
||||||
delete tab.value[k]
|
|
||||||
tab.length -= 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case 'set': // []string
|
case 'set': // []string
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import usePreferencesStore from 'stores/preferences.js'
|
import usePreferencesStore from 'stores/preferences.js'
|
||||||
import { createDiscreteApi, darkTheme } from 'naive-ui'
|
import { createDiscreteApi, darkTheme } from 'naive-ui'
|
||||||
import { themeOverrides } from '@/utils/theme.js'
|
import { darkThemeOverrides, themeOverrides } from '@/utils/theme.js'
|
||||||
import { i18nGlobal } from '@/utils/i18n.js'
|
import { i18nGlobal } from '@/utils/i18n.js'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
@ -109,6 +109,7 @@ export async function setupDiscreteApi() {
|
||||||
containerStyle: {
|
containerStyle: {
|
||||||
marginBottom: '38px',
|
marginBottom: '38px',
|
||||||
},
|
},
|
||||||
|
themeOverrides: prefStore.isDark ? darkThemeOverrides.Message : themeOverrides.Message,
|
||||||
},
|
},
|
||||||
notificationProviderProps: {
|
notificationProviderProps: {
|
||||||
max: 5,
|
max: 5,
|
||||||
|
|
Loading…
Reference in New Issue