refactor: refactoring the refresh logic for all complex types after adding new fields
This commit is contained in:
parent
45e9c49f26
commit
d88fd35e9d
|
@ -7,6 +7,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/redis/go-redis/v9"
|
"github.com/redis/go-redis/v9"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -16,7 +17,6 @@ import (
|
||||||
"tinyrdm/backend/consts"
|
"tinyrdm/backend/consts"
|
||||||
"tinyrdm/backend/types"
|
"tinyrdm/backend/types"
|
||||||
"tinyrdm/backend/utils/coll"
|
"tinyrdm/backend/utils/coll"
|
||||||
maputil "tinyrdm/backend/utils/map"
|
|
||||||
redis2 "tinyrdm/backend/utils/redis"
|
redis2 "tinyrdm/backend/utils/redis"
|
||||||
sliceutil "tinyrdm/backend/utils/slice"
|
sliceutil "tinyrdm/backend/utils/slice"
|
||||||
strutil "tinyrdm/backend/utils/string"
|
strutil "tinyrdm/backend/utils/string"
|
||||||
|
@ -1147,28 +1147,40 @@ func (b *browserService) AddHashField(connName string, db int, k any, action int
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
updated := map[string]any{}
|
var updated []types.HashEntryItem
|
||||||
|
var added []types.HashEntryItem
|
||||||
switch action {
|
switch action {
|
||||||
case 1:
|
case 1:
|
||||||
// ignore duplicated fields
|
// ignore duplicated fields
|
||||||
for i := 0; i < len(fieldItems); i += 2 {
|
for i := 0; i < len(fieldItems); i += 2 {
|
||||||
_, err = client.HSetNX(ctx, key, fieldItems[i].(string), fieldItems[i+1]).Result()
|
field, value := strutil.DecodeRedisKey(fieldItems[i]), strutil.DecodeRedisKey(fieldItems[i+1])
|
||||||
if err == nil {
|
if succ, _ := client.HSetNX(ctx, key, field, value).Result(); succ {
|
||||||
updated[fieldItems[i].(string)] = fieldItems[i+1]
|
added = append(added, types.HashEntryItem{
|
||||||
|
Key: field,
|
||||||
|
Value: value,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// overwrite duplicated fields
|
// overwrite duplicated fields
|
||||||
total := len(fieldItems)
|
total := len(fieldItems)
|
||||||
if total > 1 {
|
if total > 1 {
|
||||||
_, err = client.Pipelined(ctx, func(pipe redis.Pipeliner) error {
|
|
||||||
for i := 0; i < total; i += 2 {
|
for i := 0; i < total; i += 2 {
|
||||||
client.HSet(ctx, key, fieldItems[i], fieldItems[i+1])
|
field, value := strutil.DecodeRedisKey(fieldItems[i]), strutil.DecodeRedisKey(fieldItems[i+1])
|
||||||
}
|
if affect, _ := client.HSet(ctx, key, field, value).Result(); affect > 0 {
|
||||||
return nil
|
added = append(added, types.HashEntryItem{
|
||||||
|
Key: field,
|
||||||
|
Value: value,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
})
|
})
|
||||||
for i := 0; i < total; i += 2 {
|
} else {
|
||||||
updated[fieldItems[i].(string)] = fieldItems[i+1]
|
updated = append(updated, types.HashEntryItem{
|
||||||
|
Key: field,
|
||||||
|
Value: value,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1178,8 +1190,12 @@ func (b *browserService) AddHashField(connName string, db int, k any, action int
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
resp.Data = struct {
|
||||||
"updated": updated,
|
Added []types.HashEntryItem `json:"added,omitempty"`
|
||||||
|
Updated []types.HashEntryItem `json:"updated,omitempty"`
|
||||||
|
}{
|
||||||
|
Added: added,
|
||||||
|
Updated: updated,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1194,16 +1210,27 @@ func (b *browserService) AddListItem(connName string, db int, k any, action int,
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
var leftPush, rightPush []any
|
var leftPush, rightPush []types.ListEntryItem
|
||||||
switch action {
|
switch action {
|
||||||
case 0:
|
case 0:
|
||||||
// push to head
|
// push to head
|
||||||
|
slices.Reverse(items)
|
||||||
_, err = client.LPush(ctx, key, items...).Result()
|
_, err = client.LPush(ctx, key, items...).Result()
|
||||||
leftPush = append(leftPush, items...)
|
for i := len(items) - 1; i >= 0; i-- {
|
||||||
|
leftPush = append(leftPush, types.ListEntryItem{
|
||||||
|
Value: items[i],
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// append to tail
|
// append to tail
|
||||||
_, err = client.RPush(ctx, key, items...).Result()
|
_, err = client.RPush(ctx, key, items...).Result()
|
||||||
rightPush = append(rightPush, items...)
|
for _, it := range items {
|
||||||
|
rightPush = append(rightPush, types.ListEntryItem{
|
||||||
|
Value: it,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
|
@ -1211,9 +1238,12 @@ func (b *browserService) AddListItem(connName string, db int, k any, action int,
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
resp.Data = struct {
|
||||||
"left": leftPush,
|
Left []types.ListEntryItem `json:"left,omitempty"`
|
||||||
"right": rightPush,
|
Right []types.ListEntryItem `json:"right,omitempty"`
|
||||||
|
}{
|
||||||
|
Left: leftPush,
|
||||||
|
Right: rightPush,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1278,11 +1308,26 @@ func (b *browserService) SetSetItem(server string, db int, k any, remove bool, m
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
|
var added, removed []types.SetEntryItem
|
||||||
var affected int64
|
var affected int64
|
||||||
if remove {
|
if remove {
|
||||||
affected, err = client.SRem(ctx, key, members...).Result()
|
for _, member := range members {
|
||||||
|
if affected, _ = client.SRem(ctx, key, member).Result(); affected > 0 {
|
||||||
|
removed = append(removed, types.SetEntryItem{
|
||||||
|
Value: member,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
affected, err = client.SAdd(ctx, key, members...).Result()
|
for _, member := range members {
|
||||||
|
if affected, _ = client.SAdd(ctx, key, member).Result(); affected > 0 {
|
||||||
|
added = append(added, types.SetEntryItem{
|
||||||
|
Value: member,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
|
@ -1290,8 +1335,14 @@ func (b *browserService) SetSetItem(server string, db int, k any, remove bool, m
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
resp.Data = struct {
|
||||||
"affected": affected,
|
Added []types.SetEntryItem `json:"added,omitempty"`
|
||||||
|
Removed []types.SetEntryItem `json:"removed,omitempty"`
|
||||||
|
Affected int64 `json:"affected"`
|
||||||
|
}{
|
||||||
|
Added: added,
|
||||||
|
Removed: removed,
|
||||||
|
Affected: affected,
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1404,20 +1455,37 @@ func (b *browserService) AddZSetValue(connName string, db int, k any, action int
|
||||||
|
|
||||||
client, ctx := item.client, item.ctx
|
client, ctx := item.client, item.ctx
|
||||||
key := strutil.DecodeRedisKey(k)
|
key := strutil.DecodeRedisKey(k)
|
||||||
members := maputil.ToSlice(valueScore, func(k string) redis.Z {
|
|
||||||
return redis.Z{
|
|
||||||
Score: valueScore[k],
|
|
||||||
Member: k,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
var added, updated []types.ZSetEntryItem
|
||||||
switch action {
|
switch action {
|
||||||
case 1:
|
case 1:
|
||||||
// ignore duplicated fields
|
// ignore duplicated fields
|
||||||
_, err = client.ZAddNX(ctx, key, members...).Result()
|
for m, s := range valueScore {
|
||||||
|
if affect, _ := client.ZAddNX(ctx, key, redis.Z{Score: s, Member: m}).Result(); affect > 0 {
|
||||||
|
added = append(added, types.ZSetEntryItem{
|
||||||
|
Score: s,
|
||||||
|
Value: m,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
// overwrite duplicated fields
|
// overwrite duplicated fields
|
||||||
_, err = client.ZAdd(ctx, key, members...).Result()
|
for m, s := range valueScore {
|
||||||
|
if affect, _ := client.ZAdd(ctx, key, redis.Z{Score: s, Member: m}).Result(); affect > 0 {
|
||||||
|
added = append(added, types.ZSetEntryItem{
|
||||||
|
Score: s,
|
||||||
|
Value: m,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
updated = append(updated, types.ZSetEntryItem{
|
||||||
|
Score: s,
|
||||||
|
Value: m,
|
||||||
|
DisplayValue: "", // TODO: convert to display value
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
resp.Msg = err.Error()
|
resp.Msg = err.Error()
|
||||||
|
@ -1425,6 +1493,13 @@ func (b *browserService) AddZSetValue(connName string, db int, k any, action int
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
|
resp.Data = struct {
|
||||||
|
Added []types.ZSetEntryItem `json:"added,omitempty"`
|
||||||
|
Updated []types.ZSetEntryItem `json:"updated,omitempty"`
|
||||||
|
}{
|
||||||
|
Added: added,
|
||||||
|
Updated: updated,
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1449,9 +1524,24 @@ func (b *browserService) AddStreamValue(connName string, db int, k any, ID strin
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateValues := make(map[string]any, len(fieldItems)/2)
|
||||||
|
for i := 0; i < len(fieldItems)/2; i += 2 {
|
||||||
|
updateValues[fieldItems[i].(string)] = fieldItems[i+1]
|
||||||
|
}
|
||||||
|
vb, _ := json.Marshal(updateValues)
|
||||||
|
displayValue, _, _ := strutil.ConvertTo(string(vb), types.DECODE_NONE, types.FORMAT_JSON)
|
||||||
|
|
||||||
resp.Success = true
|
resp.Success = true
|
||||||
resp.Data = map[string]any{
|
resp.Data = struct {
|
||||||
"updateID": updateID,
|
Added []types.StreamEntryItem `json:"added,omitempty"`
|
||||||
|
}{
|
||||||
|
Added: []types.StreamEntryItem{
|
||||||
|
{
|
||||||
|
ID: updateID,
|
||||||
|
Value: updateValues,
|
||||||
|
DisplayValue: displayValue, // TODO: convert to display value
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,7 +384,6 @@ defineExpose({
|
||||||
t-tooltip="interface.load_all_entries"
|
t-tooltip="interface.load_all_entries"
|
||||||
@click="emit('loadall')" />
|
@click="emit('loadall')" />
|
||||||
</n-button-group>
|
</n-button-group>
|
||||||
{{ valueColumn.align }}
|
|
||||||
<n-button :focusable="false" plain @click="onAddRow">
|
<n-button :focusable="false" plain @click="onAddRow">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<n-icon :component="AddLink" size="18" />
|
<n-icon :component="AddLink" size="18" />
|
||||||
|
|
|
@ -132,7 +132,7 @@ const exThemeVars = computed(() => {
|
||||||
<n-tooltip :delay="2" :show-arrow="false" placement="right">
|
<n-tooltip :delay="2" :show-arrow="false" placement="right">
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
<n-icon :size="iconSize">
|
<n-icon :size="iconSize">
|
||||||
<component :is="m.icon" :stroke-width="3.5"></component>
|
<component :is="m.icon" :stroke-width="3.5" />
|
||||||
</n-icon>
|
</n-icon>
|
||||||
</template>
|
</template>
|
||||||
{{ m.label }}
|
{{ m.label }}
|
||||||
|
|
|
@ -6,7 +6,6 @@ import {
|
||||||
isEmpty,
|
isEmpty,
|
||||||
join,
|
join,
|
||||||
last,
|
last,
|
||||||
map,
|
|
||||||
remove,
|
remove,
|
||||||
set,
|
set,
|
||||||
size,
|
size,
|
||||||
|
@ -1058,21 +1057,26 @@ const useBrowserStore = defineStore('browser', {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* insert or update hash field item
|
* insert or update hash field item
|
||||||
* @param {string} connName
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {number }action 0:ignore duplicated fields 1:overwrite duplicated fields
|
* @param {number }action 0:ignore duplicated fields 1:overwrite duplicated fields
|
||||||
* @param {string[]} fieldItems field1, value1, filed2, value2...
|
* @param {string[]} fieldItems field1, value1, filed2, value2...
|
||||||
* @returns {Promise<{[msg]: string, success: boolean, [updated]: {}}>}
|
* @returns {Promise<{[msg]: string, success: boolean, [updated]: [], [added]: []}>}
|
||||||
*/
|
*/
|
||||||
async addHashField(connName, db, key, action, fieldItems) {
|
async addHashField(server, db, key, action, fieldItems) {
|
||||||
try {
|
try {
|
||||||
const { data, success, msg } = await AddHashField(connName, db, key, action, fieldItems)
|
const { data, success, msg } = await AddHashField(server, db, key, action, fieldItems)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updated = {} } = data
|
const { updated = [], added = [] } = data
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'hash', entries: updated })
|
if (!isEmpty(updated)) {
|
||||||
return { success, updated }
|
tab.replaceValueEntries({ server, db, key, type: 'hash', entries: updated })
|
||||||
|
}
|
||||||
|
if (!isEmpty(added)) {
|
||||||
|
tab.insertValueEntries({ server, db, key, type: 'hash', entries: added })
|
||||||
|
}
|
||||||
|
return { success, updated, added }
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
}
|
}
|
||||||
|
@ -1138,15 +1142,13 @@ const useBrowserStore = defineStore('browser', {
|
||||||
if (success) {
|
if (success) {
|
||||||
const { left = [] } = data
|
const { left = [] } = data
|
||||||
if (!isEmpty(left)) {
|
if (!isEmpty(left)) {
|
||||||
// TODO: convert to display value
|
|
||||||
const entries = map(left, (v) => ({ v }))
|
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
tab.upsertValueEntries({
|
tab.insertValueEntries({
|
||||||
server: server,
|
server: server,
|
||||||
db,
|
db,
|
||||||
key,
|
key,
|
||||||
type: 'list',
|
type: 'list',
|
||||||
entries,
|
entries: left,
|
||||||
prepend: true,
|
prepend: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1172,15 +1174,15 @@ const useBrowserStore = defineStore('browser', {
|
||||||
const { data, success, msg } = await AddListItem(server, db, key, 1, values)
|
const { data, success, msg } = await AddListItem(server, db, key, 1, values)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { right = [] } = data
|
const { right = [] } = data
|
||||||
|
// FIXME: do not append items if not all items loaded
|
||||||
if (!isEmpty(right)) {
|
if (!isEmpty(right)) {
|
||||||
const entries = map(right, (v) => ({ v }))
|
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
tab.upsertValueEntries({
|
tab.insertValueEntries({
|
||||||
server: server,
|
server: server,
|
||||||
db,
|
db,
|
||||||
key,
|
key,
|
||||||
type: 'list',
|
type: 'list',
|
||||||
entries,
|
entries: right,
|
||||||
prepend: false,
|
prepend: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1262,21 +1264,24 @@ const useBrowserStore = defineStore('browser', {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add item to set
|
* add item to set
|
||||||
* @param {string} connName
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number} key
|
* @param {string|number} key
|
||||||
* @param {string|string[]} value
|
* @param {string|string[]} value
|
||||||
* @returns {Promise<{[msg]: string, success: boolean}>}
|
* @returns {Promise<{[msg]: string, success: boolean}>}
|
||||||
*/
|
*/
|
||||||
async addSetItem(connName, db, key, value) {
|
async addSetItem(server, db, key, value) {
|
||||||
try {
|
try {
|
||||||
if ((!value) instanceof Array) {
|
if ((!value) instanceof Array) {
|
||||||
value = [value]
|
value = [value]
|
||||||
}
|
}
|
||||||
const { data, success, msg } = await SetSetItem(connName, db, key, false, value)
|
const { data, success, msg } = await SetSetItem(server, db, key, false, value)
|
||||||
if (success) {
|
if (success) {
|
||||||
|
const { added } = data
|
||||||
|
if (!isEmpty(added)) {
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'set', entries: value })
|
tab.insertValueEntries({ server, db, key, type: 'set', entries: added })
|
||||||
|
}
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1338,19 +1343,25 @@ const useBrowserStore = defineStore('browser', {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* add item to sorted set
|
* add item to sorted set
|
||||||
* @param {string} connName
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {number} action
|
* @param {number} action
|
||||||
* @param {Object.<string, number>} vs value: score
|
* @param {Object.<string, number>} vs value: score
|
||||||
* @returns {Promise<{[msg]: string, success: boolean}>}
|
* @returns {Promise<{[msg]: string, success: boolean}>}
|
||||||
*/
|
*/
|
||||||
async addZSetItem(connName, db, key, action, vs) {
|
async addZSetItem(server, db, key, action, vs) {
|
||||||
try {
|
try {
|
||||||
const { success, msg } = await AddZSetValue(connName, db, key, action, vs)
|
const { data, success, msg } = await AddZSetValue(server, db, key, action, vs)
|
||||||
const tab = useTabStore()
|
|
||||||
tab.upsertValueEntries({ server: connName, db, key, type: 'zset', entries: vs })
|
|
||||||
if (success) {
|
if (success) {
|
||||||
|
const { added, updated } = data
|
||||||
|
const tab = useTabStore()
|
||||||
|
if (!isEmpty(added)) {
|
||||||
|
tab.insertValueEntries({ server, db, key, type: 'zset', entries: added })
|
||||||
|
}
|
||||||
|
if (!isEmpty(updated)) {
|
||||||
|
tab.replaceValueEntries({ server, db, key, type: 'zset', entries: updated })
|
||||||
|
}
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
@ -1439,26 +1450,28 @@ const useBrowserStore = defineStore('browser', {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* insert new stream field item
|
* insert new stream field item
|
||||||
* @param {string} connName
|
* @param {string} server
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string|number[]} key
|
* @param {string|number[]} key
|
||||||
* @param {string} id
|
* @param {string} id
|
||||||
* @param {string[]} values field1, value1, filed2, value2...
|
* @param {string[]} values field1, value1, filed2, value2...
|
||||||
* @returns {Promise<{[msg]: string, success: boolean}>}
|
* @returns {Promise<{[msg]: string, success: boolean}>}
|
||||||
*/
|
*/
|
||||||
async addStreamValue(connName, db, key, id, values) {
|
async addStreamValue(server, db, key, id, values) {
|
||||||
try {
|
try {
|
||||||
const { data = {}, success, msg } = await AddStreamValue(connName, db, key, id, values)
|
const { data = {}, success, msg } = await AddStreamValue(server, db, key, id, values)
|
||||||
if (success) {
|
if (success) {
|
||||||
const { updateID } = data
|
const { added = [] } = data
|
||||||
|
if (!isEmpty(added)) {
|
||||||
const tab = useTabStore()
|
const tab = useTabStore()
|
||||||
tab.upsertValueEntries({
|
tab.insertValueEntries({
|
||||||
server: connName,
|
server,
|
||||||
db,
|
db,
|
||||||
key,
|
key,
|
||||||
type: 'stream',
|
type: 'stream',
|
||||||
entries: [{ id: updateID, value: values }],
|
entries: added,
|
||||||
})
|
})
|
||||||
|
}
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
return { success: false, msg }
|
return { success: false, msg }
|
||||||
|
@ -1483,8 +1496,8 @@ const useBrowserStore = defineStore('browser', {
|
||||||
try {
|
try {
|
||||||
const { data = {}, success, msg } = await RemoveStreamValues(connName, db, key, ids)
|
const { data = {}, success, msg } = await RemoveStreamValues(connName, db, key, ids)
|
||||||
if (success) {
|
if (success) {
|
||||||
const tab = useTabStore()
|
// const tab = useTabStore()
|
||||||
tab.removeValueEntries({ server: connName, db, key, type: 'stream', entries: ids })
|
// tab.removeValueEntries({ server: connName, db, key, type: 'stream', entries: ids })
|
||||||
return { success }
|
return { success }
|
||||||
} else {
|
} else {
|
||||||
return { success, msg }
|
return { success, msg }
|
||||||
|
|
|
@ -183,7 +183,7 @@ const useTabStore = defineStore('tab', {
|
||||||
* @param {number} db
|
* @param {number} db
|
||||||
* @param {string} key
|
* @param {string} key
|
||||||
* @param {string} type
|
* @param {string} type
|
||||||
* @param {string[]|Object.<string, number>|Object.<number, string>} entries
|
* @param {string[]|Object.<string, number>|Object.<number, string>|{k:string, v:string}[]} entries
|
||||||
* @param {boolean} [prepend] for list only
|
* @param {boolean} [prepend] for list only
|
||||||
* @param {boolean} [reset]
|
* @param {boolean} [reset]
|
||||||
* @param {boolean} [nocheck] ignore conflict checking for hash/set/zset
|
* @param {boolean} [nocheck] ignore conflict checking for hash/set/zset
|
||||||
|
@ -225,11 +225,32 @@ const useTabStore = defineStore('tab', {
|
||||||
} else {
|
} else {
|
||||||
tab.value = tab.value || {}
|
tab.value = tab.value || {}
|
||||||
}
|
}
|
||||||
for (const k in entries) {
|
if (entries instanceof Array) {
|
||||||
if (nocheck !== true && !tab.value.hasOwnProperty(k)) {
|
// append new item
|
||||||
tab.length += 1
|
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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
tab.value[k] = entries[k]
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -294,6 +315,117 @@ const useTabStore = defineStore('tab', {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* insert entries
|
||||||
|
* @param {string} server
|
||||||
|
* @param {number} db
|
||||||
|
* @param {string|number[]} key
|
||||||
|
* @param {string} type
|
||||||
|
* @param {any[]} entries
|
||||||
|
* @param {boolean} [prepend] for list only
|
||||||
|
*/
|
||||||
|
insertValueEntries({ server, db, key, type, entries, prepend }) {
|
||||||
|
const tab = find(this.tabList, { name: server, db, key })
|
||||||
|
if (tab == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (type.toLowerCase()) {
|
||||||
|
case 'list': // {v:string, dv:[string]}[]
|
||||||
|
tab.value = tab.value || []
|
||||||
|
if (prepend === true) {
|
||||||
|
tab.value = [...entries, ...tab.value]
|
||||||
|
} else {
|
||||||
|
tab.value.push(...entries)
|
||||||
|
}
|
||||||
|
tab.length += size(entries)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'hash': // {k:string, v:string, dv:[string]}[]
|
||||||
|
case 'set': // {v: string, s: number}[]
|
||||||
|
case 'zset': // {v: string, s: number}[]
|
||||||
|
tab.value = tab.value || []
|
||||||
|
tab.value.push(...entries)
|
||||||
|
tab.length += size(entries)
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'stream': // {id: string, v: {}}[]
|
||||||
|
tab.value = tab.value || []
|
||||||
|
tab.value = [...entries, ...tab.value]
|
||||||
|
tab.length += size(entries)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* replace entries
|
||||||
|
* @param {string} server
|
||||||
|
* @param {number} db
|
||||||
|
* @param {string|number[]} key
|
||||||
|
* @param {string} type
|
||||||
|
* @param {any[]} entries
|
||||||
|
*/
|
||||||
|
replaceValueEntries({ server, db, key, type, entries }) {
|
||||||
|
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': // {k:string, v:string, dv:string}[]
|
||||||
|
tab.value = tab.value || []
|
||||||
|
for (const entry of entries) {
|
||||||
|
let updated = false
|
||||||
|
for (const val of tab.value) {
|
||||||
|
if (val.k === entry.k) {
|
||||||
|
val.v = entry.v
|
||||||
|
val.dv = entry.dv
|
||||||
|
updated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!updated) {
|
||||||
|
// no match element, append
|
||||||
|
tab.value.push(entry)
|
||||||
|
tab.length += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
|
||||||
|
case 'zset': // {s:number, v:string, dv:string}[]
|
||||||
|
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.dv = entry.dv
|
||||||
|
updated = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!updated) {
|
||||||
|
// no match element, append
|
||||||
|
tab.value.push(entry)
|
||||||
|
tab.length += 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* remove value entries
|
* remove value entries
|
||||||
* @param {string} server
|
* @param {string} server
|
||||||
|
|
|
@ -106,6 +106,9 @@ export async function setupDiscreteApi() {
|
||||||
messageProviderProps: {
|
messageProviderProps: {
|
||||||
placement: 'bottom',
|
placement: 'bottom',
|
||||||
keepAliveOnHover: true,
|
keepAliveOnHover: true,
|
||||||
|
containerStyle: {
|
||||||
|
marginBottom: '38px',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
notificationProviderProps: {
|
notificationProviderProps: {
|
||||||
max: 5,
|
max: 5,
|
||||||
|
|
|
@ -57,9 +57,6 @@ export const themeOverrides = {
|
||||||
buttonColorActive: '#D13B37',
|
buttonColorActive: '#D13B37',
|
||||||
buttonTextColorActive: '#FFF',
|
buttonTextColorActive: '#FFF',
|
||||||
},
|
},
|
||||||
Message: {
|
|
||||||
margin: '0 0 38px 0',
|
|
||||||
},
|
|
||||||
DataTable: {
|
DataTable: {
|
||||||
thPaddingSmall: '6px 8px',
|
thPaddingSmall: '6px 8px',
|
||||||
tdPaddingSmall: '6px 8px',
|
tdPaddingSmall: '6px 8px',
|
||||||
|
|
Loading…
Reference in New Issue