From 056ee0d58e2da149ec5534b86ff068f790aec9ac Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Tue, 9 Dec 2025 13:55:21 +0100 Subject: [PATCH 01/32] Created tab for adding key, replaced modal --- packages/web/src/tabs/DbKeyTab.svelte | 145 +++++++++++++++++++++ packages/web/src/tabs/index.js | 2 + packages/web/src/widgets/DbKeysTree.svelte | 41 +++--- 3 files changed, 172 insertions(+), 16 deletions(-) create mode 100644 packages/web/src/tabs/DbKeyTab.svelte diff --git a/packages/web/src/tabs/DbKeyTab.svelte b/packages/web/src/tabs/DbKeyTab.svelte new file mode 100644 index 000000000..e4858ce53 --- /dev/null +++ b/packages/web/src/tabs/DbKeyTab.svelte @@ -0,0 +1,145 @@ + + +{#if driver && driver.supportedKeyTypes && driver.supportedKeyTypes.length > 0} + +
+
+ + { + // @ts-ignore + keyName = e.target.value; + }} + /> + + +
+ + + ({ value: t.name, label: t.label }))} + value={type} + isNative + on:change={e => { + type = e.detail; + }} + /> + + + x.name == type).dbKeyFields} + {item} + onChangeItem={value => { + item = value; + }} + /> + +
+ +
+ +
+
+
+ +{:else} +
+
+
Loading...
+
+
+{/if} + + \ No newline at end of file diff --git a/packages/web/src/tabs/index.js b/packages/web/src/tabs/index.js index 1e34e5102..00d1fcb6a 100644 --- a/packages/web/src/tabs/index.js +++ b/packages/web/src/tabs/index.js @@ -18,6 +18,7 @@ import * as JsonTab from './JsonTab.svelte'; import * as ChangelogTab from './ChangelogTab.svelte'; import * as DiagramTab from './DiagramTab.svelte'; import * as DbKeyDetailTab from './DbKeyDetailTab.svelte'; +import * as DbKeyTab from './DbKeyTab.svelte'; import * as QueryDataTab from './QueryDataTab.svelte'; import * as ConnectionTab from './ConnectionTab.svelte'; import * as MapTab from './MapTab.svelte'; @@ -50,6 +51,7 @@ export default { ChangelogTab, DiagramTab, DbKeyDetailTab, + DbKeyTab, QueryDataTab, ConnectionTab, MapTab, diff --git a/packages/web/src/widgets/DbKeysTree.svelte b/packages/web/src/widgets/DbKeysTree.svelte index 512198a44..725071e2f 100644 --- a/packages/web/src/widgets/DbKeysTree.svelte +++ b/packages/web/src/widgets/DbKeysTree.svelte @@ -51,25 +51,34 @@ function handleAddKey() { const connection = $currentDatabase?.connection; const database = $currentDatabase?.name; - const driver = findEngineDriver(connection, getExtensions()); - showModal(AddDbKeyModal, { - conid: connection._id, - database, - driver, - onConfirm: async item => { - const type = driver.supportedKeyTypes.find(x => x.name == item.type); - - await apiCall('database-connections/call-method', { - conid: connection._id, - database, - method: type.addMethod, - args: [item.keyName, ...type.dbKeyFields.map(fld => item[fld.name])], - }); - - reloadModel(); + openNewTab({ + tabComponent: 'DbKeyTab', + title: 'Add key', + icon: 'img keydb', + props: { + conid: connection?._id, + database, }, }); + + // showModal(AddDbKeyModal, { + // conid: connection._id, + // database, + // driver, + // onConfirm: async item => { + // const type = driver.supportedKeyTypes.find(x => x.name == item.type); + + // await apiCall('database-connections/call-method', { + // conid: connection._id, + // database, + // method: type.addMethod, + // args: [item.keyName, ...type.dbKeyFields.map(fld => item[fld.name])], + // }); + + // reloadModel(); + // }, + // }); } $: differentFocusedDb = From 623a23492f90cb48c595f1bf02054c0aaf95a1e0 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Tue, 9 Dec 2025 16:39:36 +0100 Subject: [PATCH 02/32] Add initial key name support in DbKeyTab and DbKeysTree components --- packages/web/src/tabs/DbKeyTab.svelte | 3 ++- packages/web/src/widgets/DbKeysTree.svelte | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/web/src/tabs/DbKeyTab.svelte b/packages/web/src/tabs/DbKeyTab.svelte index e4858ce53..f9eb19d0a 100644 --- a/packages/web/src/tabs/DbKeyTab.svelte +++ b/packages/web/src/tabs/DbKeyTab.svelte @@ -16,12 +16,13 @@ export let conid; export let database; export let tabid; + export let initialKeyName = ''; $: connection = useConnectionInfo({ conid }); $: driver = $connection && findEngineDriver($connection, getExtensions()); let item = {}; - let keyName = ''; + let keyName = initialKeyName || ''; $: type = driver?.supportedKeyTypes?.[0]?.name || ''; $: console.log('DbKeyTab debug:', { conid, database, connection: $connection, driver, hasTypes: driver?.supportedKeyTypes?.length }); diff --git a/packages/web/src/widgets/DbKeysTree.svelte b/packages/web/src/widgets/DbKeysTree.svelte index 725071e2f..e1cab368a 100644 --- a/packages/web/src/widgets/DbKeysTree.svelte +++ b/packages/web/src/widgets/DbKeysTree.svelte @@ -51,6 +51,19 @@ function handleAddKey() { const connection = $currentDatabase?.connection; const database = $currentDatabase?.name; + const focusedKey = $focusedTreeDbKey; + + let initialKeyName = ''; + if (focusedKey) { + if (focusedKey.type === 'dir' && focusedKey.key) { + initialKeyName = focusedKey.key + treeKeySeparator; + } else if (focusedKey.key) { + const lastSeparatorIndex = focusedKey.key.lastIndexOf(treeKeySeparator); + if (lastSeparatorIndex !== -1) { + initialKeyName = focusedKey.key.substring(0, lastSeparatorIndex + 1); + } + } + } openNewTab({ tabComponent: 'DbKeyTab', @@ -59,6 +72,7 @@ props: { conid: connection?._id, database, + initialKeyName, }, }); From 4a0af08ae5269ba7475fd7d17f3fbebd6666188a Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Wed, 10 Dec 2025 10:34:19 +0100 Subject: [PATCH 03/32] Update key type display in DbKeyDetailTab to use label if available --- packages/web/src/tabs/DbKeyDetailTab.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte index 6c6a92c82..33c942096 100644 --- a/packages/web/src/tabs/DbKeyDetailTab.svelte +++ b/packages/web/src/tabs/DbKeyDetailTab.svelte @@ -128,7 +128,7 @@
- {keyInfo.type} + {keyInfo.keyType?.label || keyInfo.type}
From 4772c0e110cc76338e7c54c75bf5d998761a96ae Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Wed, 10 Dec 2025 12:18:45 +0100 Subject: [PATCH 04/32] Add support for 'zadd' command and update key fields in Sorted Set configuration --- plugins/dbgate-plugin-redis/src/backend/driver.js | 4 +++- plugins/dbgate-plugin-redis/src/frontend/driver.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/plugins/dbgate-plugin-redis/src/backend/driver.js b/plugins/dbgate-plugin-redis/src/backend/driver.js index 51290159c..fb0e9bacd 100644 --- a/plugins/dbgate-plugin-redis/src/backend/driver.js +++ b/plugins/dbgate-plugin-redis/src/backend/driver.js @@ -487,6 +487,8 @@ const driver = { switch (method) { case 'mdel': return await this.deleteBranch(dbhan, args[0]); + case 'zadd': + return await dbhan.client.zadd(args[0], args[2], args[1]); case 'xaddjson': let json; try { @@ -520,7 +522,7 @@ const driver = { const res = await dbhan.client.zscan(key, cursor, 'COUNT', count); return { cursor: parseInt(res[0]), - items: _.chunk(res[1], 2).map((item) => ({ value: item[0], score: item[1] })), + items: _.chunk(res[1], 2).map((item) => ({ member: item[0], score: item[1] })), }; } case 'hash': { diff --git a/plugins/dbgate-plugin-redis/src/frontend/driver.js b/plugins/dbgate-plugin-redis/src/frontend/driver.js index 3182cbc25..80956b306 100644 --- a/plugins/dbgate-plugin-redis/src/frontend/driver.js +++ b/plugins/dbgate-plugin-redis/src/frontend/driver.js @@ -55,8 +55,8 @@ const driver = { { name: 'zset', label: 'Sorted Set', - dbKeyFields: [{ name: 'score' }, { name: 'value' }], - keyColumn: 'value', + dbKeyFields: [{ name: 'member' }, { name: 'score' }], + keyColumn: 'member', addMethod: 'zadd', showItemList: true, }, From f30b96b360d7d60cfdda361063d2efb03f92fe02 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Wed, 10 Dec 2025 12:34:28 +0100 Subject: [PATCH 05/32] Refactor DbKeyDetailTab to use ToolStrip for action buttons and improve layout structure --- packages/web/src/tabs/DbKeyDetailTab.svelte | 108 +++++++++++--------- 1 file changed, 60 insertions(+), 48 deletions(-) diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte index 33c942096..d876a898e 100644 --- a/packages/web/src/tabs/DbKeyDetailTab.svelte +++ b/packages/web/src/tabs/DbKeyDetailTab.svelte @@ -36,6 +36,8 @@ import SelectField from '../forms/SelectField.svelte'; import DbKeyValueDetail from '../dbkeyvalue/DbKeyValueDetail.svelte'; import { _t } from '../translations'; + import ToolStripContainer from '../buttons/ToolStripContainer.svelte'; + import ToolStripButton from '../buttons/ToolStripButton.svelte'; export let tabid; export let conid; @@ -124,59 +126,69 @@ {#await apiCall('database-connections/load-key-info', { conid, database, key, refreshToken })} {:then keyInfo} -
-
-
- - {keyInfo.keyType?.label || keyInfo.type} + +
+
+
+ + {keyInfo.keyType?.label || keyInfo.type} +
+
+ +
+ handleChangeTtl(keyInfo)} />
-
- -
- handleChangeTtl(keyInfo)} /> - {#if keyInfo.type == 'string'} - - {/if} - {#if keyInfo.keyType?.addMethod && keyInfo.keyType?.showItemList} - addItem(keyInfo)} /> - {/if} - -
-
- {#if keyInfo.keyType?.dbKeyFields && keyInfo.keyType?.showItemList} - - - { - currentRow = row; +
+ {#if keyInfo.keyType?.dbKeyFields && keyInfo.keyType?.showItemList} + + + { + currentRow = row; + }} + /> + + + f.name === 'value') + : keyInfo.keyType.dbKeyFields} + item={currentRow} + /> + + + {:else} +
+ { + editedValue = value; }} /> - - - - - - {:else} -
- { - editedValue = value; - }} - /> -
- {/if} +
+ {/if} +
-
+ + + {#if keyInfo.type == 'string'} + {_t('common.save', { defaultMessage: 'Save' })} + {/if} + {#if keyInfo.keyType?.addMethod && keyInfo.keyType?.showItemList} + addItem(keyInfo)}>Add item + {/if} + {_t('common.refresh', { defaultMessage: 'Refresh' })} + + {/await} \ No newline at end of file diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte index 643d33015..5d869a00d 100644 --- a/packages/web/src/tabs/DbKeyDetailTab.svelte +++ b/packages/web/src/tabs/DbKeyDetailTab.svelte @@ -29,7 +29,7 @@ import { showModal } from '../modals/modalTools'; import InputTextModal from '../modals/InputTextModal.svelte'; import _ from 'lodash'; - import DbKeyItemDetail from '../dbkeyvalue/DbKeyItemDetail.svelte'; + import DbKeyItemEdit from '../dbkeyvalue/DbKeyItemEdit.svelte'; import DbKeyAddItemModal from '../modals/DbKeyAddItemModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import { changeTab } from '../utility/common'; @@ -304,7 +304,7 @@ /> - f.name === 'value') : keyInfo.keyType.dbKeyFields} From f9c47ab2331ebec4ecedb97b6c6fbf7b55fbf6b1 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Thu, 18 Dec 2025 12:37:12 +0100 Subject: [PATCH 18/32] Add DbKeyValueHashEdit component for editing hash key values in DbKeyTab --- .../src/dbkeyvalue/DbKeyValueHashEdit.svelte | 122 ++++++++++++++++++ packages/web/src/tabs/DbKeyTab.svelte | 73 +++++++---- 2 files changed, 169 insertions(+), 26 deletions(-) create mode 100644 packages/web/src/dbkeyvalue/DbKeyValueHashEdit.svelte diff --git a/packages/web/src/dbkeyvalue/DbKeyValueHashEdit.svelte b/packages/web/src/dbkeyvalue/DbKeyValueHashEdit.svelte new file mode 100644 index 000000000..20f1e13b6 --- /dev/null +++ b/packages/web/src/dbkeyvalue/DbKeyValueHashEdit.svelte @@ -0,0 +1,122 @@ + + +
+ {#each records as record, index} +
+
+ + handleFieldChange(index, 'key', e.target.value)} + disabled={keyColumn === 'key'} + /> + +
+
+ + handleFieldChange(index, 'value', e.target.value)} + disabled={keyColumn === 'value'} + /> + +
+
+ + handleFieldChange(index, 'ttl', e.target.value)} + disabled={keyColumn === 'ttl'} + /> + +
+
+ {/each} + +
+ +
+
+ + \ No newline at end of file diff --git a/packages/web/src/tabs/DbKeyTab.svelte b/packages/web/src/tabs/DbKeyTab.svelte index f9eb19d0a..3b9b1d661 100644 --- a/packages/web/src/tabs/DbKeyTab.svelte +++ b/packages/web/src/tabs/DbKeyTab.svelte @@ -1,5 +1,6 @@ + +
+ {#each records as record, index} +
+
+ + handleFieldChange(index, 'value', e.target.value)} + disabled={keyColumn === 'value'} + /> + +
+
+ {/each} + +
+ +
+
+ + diff --git a/packages/web/src/dbkeyvalue/DbKeyValueSetEdit.svelte b/packages/web/src/dbkeyvalue/DbKeyValueSetEdit.svelte new file mode 100644 index 000000000..259b6fc57 --- /dev/null +++ b/packages/web/src/dbkeyvalue/DbKeyValueSetEdit.svelte @@ -0,0 +1,97 @@ + + +
+ {#each records as record, index} +
+
+ + handleFieldChange(index, 'value', e.target.value)} + disabled={keyColumn === 'value'} + /> + +
+
+ {/each} + +
+ +
+
+ + diff --git a/packages/web/src/dbkeyvalue/DbKeyValueStreamEdit.svelte b/packages/web/src/dbkeyvalue/DbKeyValueStreamEdit.svelte new file mode 100644 index 000000000..2cf328fb6 --- /dev/null +++ b/packages/web/src/dbkeyvalue/DbKeyValueStreamEdit.svelte @@ -0,0 +1,112 @@ + + +
+ {#each records as record, index} +
+
+ + handleFieldChange(index, 'id', e.target.value)} + disabled={keyColumn === 'id'} + placeholder="* for auto" + /> + +
+
+ + handleFieldChange(index, 'value', e.target.value)} + disabled={keyColumn === 'value'} + /> + +
+
+ {/each} + +
+ +
+
+ + diff --git a/packages/web/src/dbkeyvalue/DbKeyValueZSetEdit.svelte b/packages/web/src/dbkeyvalue/DbKeyValueZSetEdit.svelte new file mode 100644 index 000000000..0dbe03f0f --- /dev/null +++ b/packages/web/src/dbkeyvalue/DbKeyValueZSetEdit.svelte @@ -0,0 +1,111 @@ + + +
+ {#each records as record, index} +
+
+ + handleFieldChange(index, 'member', e.target.value)} + disabled={keyColumn === 'member'} + /> + +
+
+ + handleFieldChange(index, 'score', e.target.value)} + disabled={keyColumn === 'score'} + /> + +
+
+ {/each} + +
+ +
+
+ + diff --git a/packages/web/src/tabs/DbKeyTab.svelte b/packages/web/src/tabs/DbKeyTab.svelte index 3b9b1d661..8aaaa8fe3 100644 --- a/packages/web/src/tabs/DbKeyTab.svelte +++ b/packages/web/src/tabs/DbKeyTab.svelte @@ -1,6 +1,10 @@ {#await apiCall('database-connections/load-key-info', { conid, database, key, refreshToken })} @@ -304,17 +241,15 @@ />
- f.name === 'value') - : keyInfo.keyType.dbKeyFields} + { - const existingChange = changeSetRedis.changes.find( - c => c.key === keyInfo.key && c.type === keyInfo.type - ); - - if (keyInfo.type === 'hash') { + const existingChange = changeSetRedis.changes.find( + c => c.key === keyInfo.key && c.type === keyInfo.type + ); + + if (keyInfo.type === 'hash') { // @ts-ignore const hashChange = existingChange || { key: keyInfo.key, type: 'hash', inserts: [], updates: [], deletes: [] }; // @ts-ignore @@ -365,8 +300,6 @@ value={getDisplayValue(keyInfo)} keyType={keyInfo.type} onChangeValue={value => { - editedValue = value; - if (keyInfo.type === 'string') { addOrUpdateChange({ key: key, @@ -391,15 +324,8 @@ Save All Changes - {#if keyInfo.type == 'string'} - {_t('common.save', { defaultMessage: 'Save' })} - {/if} + disabled={!hasChanges} + >{_t('common.save', { defaultMessage: 'Save' })} {#if keyInfo.keyType?.addMethod && keyInfo.keyType?.showItemList} addItem(keyInfo)}>Add field {/if} From e6c938e5d054f4b52ca479671ec889b37313fdd9 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Fri, 19 Dec 2025 13:46:09 +0100 Subject: [PATCH 25/32] Implement saveRedisData functionality and update API call in DbKeyDetailTab --- .../src/controllers/databaseConnections.js | 14 +++++++++++ .../api/src/proc/databaseConnectionProcess.js | 25 +++++++++++++++++++ packages/web/src/tabs/DbKeyDetailTab.svelte | 2 +- 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/packages/api/src/controllers/databaseConnections.js b/packages/api/src/controllers/databaseConnections.js index 161ab1e32..79785f644 100644 --- a/packages/api/src/controllers/databaseConnections.js +++ b/packages/api/src/controllers/databaseConnections.js @@ -494,6 +494,20 @@ module.exports = { return res.result || null; }, + saveRedisData_meta: true, + async saveRedisData({ conid, database, changeSet }, req) { + await testConnectionPermission(conid, req); + + const opened = await this.ensureOpened(conid, database); + const res = await this.sendRequest(opened, { msgtype: 'saveRedisData', changeSet }); + if (res.errorMessage) { + return { + errorMessage: res.errorMessage, + }; + } + return res.result || null; + }, + status_meta: true, async status({ conid, database }, req) { if (!conid) { diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index bed349355..e360311a5 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -368,6 +368,30 @@ async function handleSaveTableData({ msgid, changeSet }) { } } +async function handleSaveRedisData({ msgid, changeSet }) { + try { + const driver = requireEngineDriver(storedConnection); + + if (!changeSet || !changeSet.changes || !Array.isArray(changeSet.changes)) { + throw new Error('Invalid changeSet structure'); + } + + for (const change of changeSet.changes) { + if (change.type === 'string') { + await driver.query(dbhan, `SET "${change.key}" "${change.value}"`); + } + } + + process.send({ msgtype: 'response', msgid }); + } catch (err) { + process.send({ + msgtype: 'response', + msgid, + errorMessage: extractErrorMessage(err, 'Error saving Redis data'), + }); + } +} + async function handleSqlPreview({ msgid, objects, options }) { await waitStructure(); const driver = requireEngineDriver(storedConnection); @@ -501,6 +525,7 @@ const messageHandlers = { schemaList: handleSchemaList, executeSessionQuery: handleExecuteSessionQuery, evalJsonScript: handleEvalJsonScript, + saveRedisData: handleSaveRedisData, // runCommand: handleRunCommand, }; diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte index b470a2c7e..1631a98e1 100644 --- a/packages/web/src/tabs/DbKeyDetailTab.svelte +++ b/packages/web/src/tabs/DbKeyDetailTab.svelte @@ -198,7 +198,7 @@ async function saveAll() { console.log('Saving all changes:', changeSetRedis); - await apiCall('database-connections/apply-redis-change-set', { + await apiCall('database-connections/save-redis-data', { conid, database, changeSet: changeSetRedis, From 8cd09342e1cd0f2fe1c2e0a8906542c0382d8645 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Fri, 19 Dec 2025 15:10:30 +0100 Subject: [PATCH 26/32] Add read-only attribute to Redis driver key fields --- plugins/dbgate-plugin-redis/src/frontend/driver.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/dbgate-plugin-redis/src/frontend/driver.js b/plugins/dbgate-plugin-redis/src/frontend/driver.js index 8a74b4685..c7424627d 100644 --- a/plugins/dbgate-plugin-redis/src/frontend/driver.js +++ b/plugins/dbgate-plugin-redis/src/frontend/driver.js @@ -47,7 +47,7 @@ const driver = { { name: 'set', label: 'Set', - dbKeyFields: [{ name: 'value' }], + dbKeyFields: [{ name: 'value', readOnly: true }], keyColumn: 'value', addMethod: 'sadd', showItemList: true, @@ -71,7 +71,7 @@ const driver = { { name: 'stream', label: 'Stream', - dbKeyFields: [{ name: 'id', readOnly: true }, { name: 'value' }], + dbKeyFields: [{ name: 'id', readOnly: true }, { name: 'value', readOnly: true }], keyColumn: 'id', addMethod: 'xaddjson', showItemList: true, From bcff01b0bffc0be965c9153091dd50b2650a9d02 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Fri, 19 Dec 2025 15:16:19 +0100 Subject: [PATCH 27/32] Implement handleSaveRedisData for Redis data types including JSON, hash, zset, and list --- .../api/src/proc/databaseConnectionProcess.js | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/packages/api/src/proc/databaseConnectionProcess.js b/packages/api/src/proc/databaseConnectionProcess.js index e360311a5..1ea2a362c 100644 --- a/packages/api/src/proc/databaseConnectionProcess.js +++ b/packages/api/src/proc/databaseConnectionProcess.js @@ -379,6 +379,32 @@ async function handleSaveRedisData({ msgid, changeSet }) { for (const change of changeSet.changes) { if (change.type === 'string') { await driver.query(dbhan, `SET "${change.key}" "${change.value}"`); + } else if (change.type === 'json') { + await driver.query(dbhan, `JSON.SET "${change.key}" $ '${change.value.replace(/'/g, "\\'")}'`); + } else if (change.type === 'hash') { + if (change.updates && Array.isArray(change.updates)) { + for (const update of change.updates) { + await driver.query(dbhan, `HSET "${change.key}" "${update.key}" "${update.value}"`); + + if (update.ttl !== undefined && update.ttl !== null && update.ttl !== -1) { + try { + await dbhan.client.call('HEXPIRE', change.key, update.ttl, 'FIELDS', 1, update.key); + } catch (e) {} + } + } + } + } else if (change.type === 'zset') { + if (change.updates && Array.isArray(change.updates)) { + for (const update of change.updates) { + await driver.query(dbhan, `ZADD "${change.key}" ${update.score} "${update.member}"`); + } + } + } else if (change.type === 'list') { + if (change.updates && Array.isArray(change.updates)) { + for (const update of change.updates) { + await driver.query(dbhan, `LSET "${change.key}" ${update.index} "${update.value}"`); + } + } } } From 7ff84a9932ec767ebbfe85031d19816cc0cd1369 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Fri, 19 Dec 2025 15:40:09 +0100 Subject: [PATCH 28/32] Refactor DbKeyDetailTab to integrate Redis data type editors for list, hash, zset, set, and stream --- packages/web/src/tabs/DbKeyDetailTab.svelte | 71 +++++++++++++++++++-- 1 file changed, 66 insertions(+), 5 deletions(-) diff --git a/packages/web/src/tabs/DbKeyDetailTab.svelte b/packages/web/src/tabs/DbKeyDetailTab.svelte index 1631a98e1..4954d48c5 100644 --- a/packages/web/src/tabs/DbKeyDetailTab.svelte +++ b/packages/web/src/tabs/DbKeyDetailTab.svelte @@ -30,6 +30,11 @@ import InputTextModal from '../modals/InputTextModal.svelte'; import _ from 'lodash'; import DbKeyItemDetail from '../dbkeyvalue/DbKeyItemDetail.svelte'; + import DbKeyValueListEdit from '../dbkeyvalue/DbKeyValueListEdit.svelte'; + import DbKeyValueHashEdit from '../dbkeyvalue/DbKeyValueHashEdit.svelte'; + import DbKeyValueZSetEdit from '../dbkeyvalue/DbKeyValueZSetEdit.svelte'; + import DbKeyValueSetEdit from '../dbkeyvalue/DbKeyValueSetEdit.svelte'; + import DbKeyValueStreamEdit from '../dbkeyvalue/DbKeyValueStreamEdit.svelte'; import DbKeyAddItemModal from '../modals/DbKeyAddItemModal.svelte'; import ErrorMessageModal from '../modals/ErrorMessageModal.svelte'; import { changeTab } from '../utility/common'; @@ -57,6 +62,7 @@ } let currentRow; + let showAddForm = false; $: key = $activeDbKeysStore[`${conid}:${database}`]; let refreshToken = 0; @@ -236,15 +242,69 @@ {changeSetRedis} onChangeSelected={row => { currentRow = row; + showAddForm = false; }} modifyRow={row => getDisplayRow(row, keyInfo)} /> - { + {#if showAddForm} + {#if keyInfo.type === 'list'} + { + console.log('Add item:', item); + showAddForm = false; + }} + /> + {:else if keyInfo.type === 'hash'} + { + console.log('Add item:', item); + showAddForm = false; + }} + /> + {:else if keyInfo.type === 'zset'} + { + console.log('Add item:', item); + showAddForm = false; + }} + /> + {:else if keyInfo.type === 'set'} + { + console.log('Add item:', item); + showAddForm = false; + }} + /> + {:else if keyInfo.type === 'stream'} + { + console.log('Add item:', item); + showAddForm = false; + }} + /> + {/if} + {:else} + { const existingChange = changeSetRedis.changes.find( c => c.key === keyInfo.key && c.type === keyInfo.type ); @@ -290,7 +350,8 @@ addOrUpdateChange(zsetChange); } }} - /> + /> + {/if} {:else} From 4c12ee3b146d32831a1a3a492098773fba8960c0 Mon Sep 17 00:00:00 2001 From: Stela Augustinova Date: Tue, 23 Dec 2025 09:05:04 +0100 Subject: [PATCH 29/32] Added delete functionality for list, hash, set, zset and stream fields. --- .../web/src/dbkeyvalue/DbKeyItemDetail.svelte | 2 +- .../web/src/dbkeyvalue/DbKeyItemEdit.svelte | 4 -- .../src/dbkeyvalue/DbKeyValueDetail.svelte | 2 +- .../src/dbkeyvalue/DbKeyValueHashEdit.svelte | 42 +++++++++++++++++- .../src/dbkeyvalue/DbKeyValueListEdit.svelte | 44 ++++++++++++++++++- .../src/dbkeyvalue/DbKeyValueSetEdit.svelte | 44 ++++++++++++++++++- .../dbkeyvalue/DbKeyValueStreamEdit.svelte | 44 ++++++++++++++++++- .../src/dbkeyvalue/DbKeyValueZSetEdit.svelte | 44 ++++++++++++++++++- packages/web/src/modals/AddDbKeyModal.svelte | 25 ++++++++--- packages/web/src/tabs/DbKeyDetailTab.svelte | 12 ++--- 10 files changed, 239 insertions(+), 24 deletions(-) diff --git a/packages/web/src/dbkeyvalue/DbKeyItemDetail.svelte b/packages/web/src/dbkeyvalue/DbKeyItemDetail.svelte index 31efe9af0..d4be24ea6 100644 --- a/packages/web/src/dbkeyvalue/DbKeyItemDetail.svelte +++ b/packages/web/src/dbkeyvalue/DbKeyItemDetail.svelte @@ -10,7 +10,7 @@
{#each dbKeyFields as column} { diff --git a/packages/web/src/dbkeyvalue/DbKeyItemEdit.svelte b/packages/web/src/dbkeyvalue/DbKeyItemEdit.svelte index c72a84179..395b80753 100644 --- a/packages/web/src/dbkeyvalue/DbKeyItemEdit.svelte +++ b/packages/web/src/dbkeyvalue/DbKeyItemEdit.svelte @@ -39,8 +39,6 @@