From 08c42ca85c7671ef67a22743132dc3bf6e461792 Mon Sep 17 00:00:00 2001 From: Lykin <137850705+tiny-craft@users.noreply.github.com> Date: Wed, 13 Dec 2023 11:48:27 +0800 Subject: [PATCH] refactor: move checked keys mark from tree view to tab store fix: deleting message may not disappear #102 fix: some error in check mode --- .../src/components/sidebar/BrowserPane.vue | 10 ++-- .../src/components/sidebar/BrowserTree.vue | 49 ++++++++++--------- frontend/src/stores/browser.js | 38 ++++++++------ frontend/src/stores/tab.js | 45 ++++++++++++++++- 4 files changed, 98 insertions(+), 44 deletions(-) diff --git a/frontend/src/components/sidebar/BrowserPane.vue b/frontend/src/components/sidebar/BrowserPane.vue index 5bb61fc..1cfcc17 100644 --- a/frontend/src/components/sidebar/BrowserPane.vue +++ b/frontend/src/components/sidebar/BrowserPane.vue @@ -4,7 +4,7 @@ import BrowserTree from './BrowserTree.vue' import IconButton from '@/components/common/IconButton.vue' import useTabStore from 'stores/tab.js' import { computed, nextTick, onMounted, reactive, ref, unref } from 'vue' -import { find, map } from 'lodash' +import { find, map, size } from 'lodash' import Refresh from '@/components/icons/Refresh.vue' import useDialogStore from 'stores/dialog.js' import { useI18n } from 'vue-i18n' @@ -43,7 +43,6 @@ const browserTreeRef = ref(null) const loading = ref(false) const fullyLoaded = ref(false) const inCheckState = ref(false) -const checkedCount = ref(0) const dbSelectOptions = computed(() => { const dblist = browserStore.getDBList(props.server) @@ -80,10 +79,14 @@ const loadProgress = computed(() => { return (db.keys * 100) / Math.max(db.keys, db.maxKeys) }) +const checkedCount = computed(() => { + return size(tabStore.getCheckedKeys(props.server)) +}) + const checkedTip = computed(() => { const dblist = browserStore.getDBList(props.server) const db = find(dblist, { db: props.db }) - return `${checkedCount.value} / ${db.maxKeys}` + return `${checkedCount.value} / ${Math.max(db.maxKeys, checkedCount.value)}` }) const onReload = async () => { @@ -267,7 +270,6 @@ onMounted(() => onReload()) { if (!props.checkMode) { - resetCheckedKey() + tabStore.setCheckedKeys(props.server) } - emit('update:checked-count', size(checkedKeys.keys)) }, { flush: 'post' }, ) @@ -76,6 +68,19 @@ const selectedKeys = computed(() => { return [] }) +/** + * + * @type {ComputedRef} + */ +const checkedKeys = computed(() => { + const tab = find(tabStore.tabList, { name: props.server }) + if (tab != null) { + const checkedKeys = get(tab, 'checkedKeys', []) + return map(checkedKeys, 'key') + } + return [] +}) + const data = computed(() => { // const dbs = get(browserStore.databases, props.server, []) // return dbs @@ -193,11 +198,6 @@ const resetExpandKey = (server, db, includeDB) => { }) } -const resetCheckedKey = () => { - checkedKeys.keys = [] - checkedKeys.redisKeys = [] -} - const handleSelectContextMenu = (key) => { contextMenuParam.show = false const selectedKey = get(selectedKeys.value, 0) @@ -333,11 +333,11 @@ const onUpdateExpanded = (value, option, meta) => { * @param {TreeOption[]} options */ const onUpdateCheckedKeys = (keys, options) => { - checkedKeys.keys = keys - checkedKeys.redisKeys = map( + const checkedKeys = map( filter(options, (o) => o.type === ConnectionType.RedisValue), - (o) => o.redisKeyCode || o.redisKey, + (o) => ({ key: o.key, redisKey: o.redisKeyCode || o.redisKey }), ) + tabStore.setCheckedKeys(props.server, checkedKeys) } const renderPrefix = ({ option }) => { @@ -510,7 +510,10 @@ const calcValueMenu = () => { // render menu function icon const renderSuffix = ({ option }) => { - if ((option.type === ConnectionType.RedisDB && option.opened) || includes(selectedKeys.value, option.key)) { + if ( + (option.type === ConnectionType.RedisDB && option.opened) || + (includes(selectedKeys.value, option.key) && !props.checkMode) + ) { switch (option.type) { case ConnectionType.RedisDB: return renderIconMenu(calcDBMenu(option.opened, option.loading, option.fullLoaded)) @@ -568,11 +571,13 @@ defineExpose({ refreshTree: () => { treeKey.value = Date.now() expandedKeys.value = [] - resetCheckedKey() + tabStore.setCheckedKeys(props.server) }, deleteCheckedItems: () => { - if (!isEmpty(checkedKeys.redisKeys)) { - dialogStore.openDeleteKeyDialog(props.server, props.db, checkedKeys.redisKeys) + const checkedKeys = tabStore.currentCheckedKeys + const redisKeys = map(checkedKeys, 'redisKey') + if (!isEmpty(redisKeys)) { + dialogStore.openDeleteKeyDialog(props.server, props.db, redisKeys) } }, }) @@ -591,7 +596,7 @@ defineExpose({ :cancelable="false" :cascade="true" :checkable="props.checkMode" - :checked-keys="checkedKeys.keys" + :checked-keys="checkedKeys" :data="data" :expand-on-click="false" :expanded-keys="expandedKeys" diff --git a/frontend/src/stores/browser.js b/frontend/src/stores/browser.js index 6705f7e..6fcb392 100644 --- a/frontend/src/stores/browser.js +++ b/frontend/src/stores/browser.js @@ -1875,26 +1875,32 @@ const useBrowserStore = defineStore('browser', { * @return {Promise} */ async deleteKeys(server, db, keys) { - const delMsgRef = $message.loading('', { duration: 0 }) + const delMsgRef = $message.loading('', { duration: 0, closable: true }) let progress = 0 let count = size(keys) - let deletedCount = 0, - failCount = 0 - for (const key of keys) { - delMsgRef.content = i18nGlobal.t('dialogue.deleting_key', { - key: decodeRedisKey(key), - index: ++progress, - count, - }) - const { success } = await DeleteOneKey(server, db, key) - if (success) { - this._deleteKeyNode(server, db, key, false) - deletedCount += 1 - } else { - failCount += 1 + let deletedCount = 0 + let failCount = 0 + try { + for (const key of keys) { + delMsgRef.content = i18nGlobal.t('dialogue.deleting_key', { + key: decodeRedisKey(key), + index: ++progress, + count, + }) + const { success } = await DeleteOneKey(server, db, key) + if (success) { + this._deleteKeyNode(server, db, key, false) + deletedCount += 1 + } else { + failCount += 1 + } } + } finally { + delMsgRef.destroy() + // clear checked keys + const tab = useTabStore() + tab.setCheckedKeys(server) } - delMsgRef.destroy() // refresh model data this._tidyNode(server, db, '', true) this._updateDBMaxKeys(server, db, -deletedCount) diff --git a/frontend/src/stores/tab.js b/frontend/src/stores/tab.js index 88b359b..e5d8a4e 100644 --- a/frontend/src/stores/tab.js +++ b/frontend/src/stores/tab.js @@ -10,7 +10,7 @@ const useTabStore = defineStore('tab', { * @property {string} [title] tab title * @property {string} [icon] tab icon * @property {string[]} selectedKeys - * @property {string[]} checkdeKeys + * @property {CheckedKey[]} checkedKeys * @property {string} [type] key type * @property {*} [value] key value * @property {string} [server] server name @@ -27,6 +27,12 @@ const useTabStore = defineStore('tab', { * @param {boolean} [loading] */ + /** + * @typedef {Object} CheckedKey + * @property {string[]} key + * @property {string[]} redisKey + */ + /** * @typedef {Object} ListEntryItem * @property {string|number[]} v value @@ -124,9 +130,14 @@ const useTabStore = defineStore('tab', { }, currentSelectedKeys() { - const tab = this.currentTab() + const tab = this.currentTab return get(tab, 'selectedKeys', []) }, + + currentCheckedKeys() { + const tab = this.currentTab + return get(tab, 'checkedKeys', []) + }, }, actions: { /** @@ -660,6 +671,36 @@ const useTabStore = defineStore('tab', { } } }, + + /** + * get checked keys + * @param server + * @returns {CheckedKey[]} + */ + getCheckedKeys(server) { + let tab = find(this.tabList, { name: server }) + if (tab != null) { + return tab.checkedKeys || [] + } + return [] + }, + + /** + * set checked keys in current display browser tree + * @param {string} server + * @param {CheckedKey[]} [keys] + */ + setCheckedKeys(server, keys) { + let tab = find(this.tabList, { name: server }) + if (tab != null) { + if (isEmpty(keys)) { + // select nothing + tab.checkedKeys = [] + } else { + tab.checkedKeys = keys + } + } + }, }, })