add db key modal

This commit is contained in:
Jan Prochazka
2022-03-13 22:30:45 +01:00
parent dc34898cd8
commit 5bda092a51
10 changed files with 161 additions and 29 deletions

View File

@@ -47,6 +47,7 @@ export interface EngineDriver {
title: string; title: string;
defaultPort?: number; defaultPort?: number;
databaseEngineTypes: string[]; databaseEngineTypes: string[];
supportedKeyTypes: { name: string; label: string }[];
supportsDatabaseUrl?: boolean; supportsDatabaseUrl?: boolean;
isElectronOnly?: boolean; isElectronOnly?: boolean;
showConnectionField?: (field: string, values: any) => boolean; showConnectionField?: (field: string, values: any) => boolean;

View File

@@ -4,6 +4,7 @@ import { get } from 'svelte/store';
import { ThemeDefinition } from 'dbgate-types'; import { ThemeDefinition } from 'dbgate-types';
import ConnectionModal from '../modals/ConnectionModal.svelte'; import ConnectionModal from '../modals/ConnectionModal.svelte';
import AboutModal from '../modals/AboutModal.svelte'; import AboutModal from '../modals/AboutModal.svelte';
import AddDbKeyModal from '../modals/AddDbKeyModal.svelte';
import SettingsModal from '../settings/SettingsModal.svelte'; import SettingsModal from '../settings/SettingsModal.svelte';
import ImportExportModal from '../modals/ImportExportModal.svelte'; import ImportExportModal from '../modals/ImportExportModal.svelte';
import SqlGeneratorModal from '../modals/SqlGeneratorModal.svelte'; import SqlGeneratorModal from '../modals/SqlGeneratorModal.svelte';
@@ -217,6 +218,30 @@ registerCommand({
}, },
}); });
registerCommand({
id: 'new.dbKey',
category: 'New',
name: 'Key',
toolbar: true,
toolbarName: 'New key',
testEnabled: () => {
const driver = findEngineDriver(get(currentDatabase)?.connection, getExtensions());
return !!get(currentDatabase) && driver?.databaseEngineTypes?.includes('keyvalue');
},
onClick: async () => {
const $currentDatabase = get(currentDatabase);
const connection = _.get($currentDatabase, 'connection') || {};
const database = _.get($currentDatabase, 'name');
const driver = findEngineDriver(get(currentDatabase)?.connection, getExtensions());
showModal(AddDbKeyModal, {
conid: connection._id,
database,
driver,
});
},
});
registerCommand({ registerCommand({
id: 'new.markdown', id: 'new.markdown',
category: 'New', category: 'New',

View File

@@ -19,6 +19,9 @@
const oldIndexRef = createRef(null); const oldIndexRef = createRef(null);
async function loadNextRows() { async function loadNextRows() {
if (isLoadedAll) {
return;
}
if (isLoading) { if (isLoading) {
// console.log('ALREADY LOADING'); // console.log('ALREADY LOADING');
loadNextNeeded = true; loadNextNeeded = true;
@@ -79,7 +82,7 @@
header: 'num', header: 'num',
width: '60px', width: '60px',
}, },
...keyInfo.tableColumns.map(column => ({ ...keyInfo.keyType.dbKeyFields.map(column => ({
fieldName: column.name, fieldName: column.name,
header: column.name, header: column.name,
})), })),

View File

@@ -1,13 +1,13 @@
<script lang="ts"> <script lang="ts">
import AceEditor from '../query/AceEditor.svelte'; import AceEditor from '../query/AceEditor.svelte';
export let keyInfo; export let dbKeyFields;
export let item; export let item;
export let onChangeItem; export let onChangeItem = null;
</script> </script>
<div class="props"> <div class="props">
{#each keyInfo.tableColumns as column} {#each dbKeyFields as column}
<div class="colname">{column.name}</div> <div class="colname">{column.name}</div>
<div class="colvalue"> <div class="colvalue">
<AceEditor <AceEditor

View File

@@ -0,0 +1,58 @@
<script lang="ts">
import FormStyledButton from '../buttons/FormStyledButton.svelte';
import DbKeyItemDetail from '../dbkeyvalue/DbKeyItemDetail.svelte';
import FormProvider from '../forms/FormProvider.svelte';
import SelectField from '../forms/SelectField.svelte';
import ModalBase from './ModalBase.svelte';
import { closeCurrentModal } from './modalTools';
export let conid;
export let database;
export let driver;
export let onConfirm;
let item = {};
let type = driver.supportedKeyTypes[0].name;
const handleSubmit = async () => {
closeCurrentModal();
onConfirm(item);
};
</script>
<FormProvider>
<ModalBase {...$$restProps}>
<svelte:fragment slot="header">Add item</svelte:fragment>
<div class="container">
<SelectField
options={driver.supportedKeyTypes.map(t => ({ value: t.name, label: t.label }))}
value={type}
on:change={e => {
type = e.detail;
}}
/>
<DbKeyItemDetail
dbKeyFields={driver.supportedKeyTypes.find(x => x.name == type).dbKeyFields}
{item}
onChangeItem={value => {
item = value;
}}
/>
</div>
<svelte:fragment slot="footer">
<FormStyledButton value="OK" on:click={e => handleSubmit()} />
<FormStyledButton type="button" value="Cancel" on:click={closeCurrentModal} />
</svelte:fragment>
</ModalBase>
</FormProvider>
<style>
.container {
display: flex;
height: 30vh;
}
</style>

View File

@@ -24,7 +24,7 @@
<div class="container"> <div class="container">
<DbKeyItemDetail <DbKeyItemDetail
{keyInfo} dbKeyFields={keyInfo.keyType.dbKeyFields}
{item} {item}
onChangeItem={value => { onChangeItem={value => {
item = value; item = value;

View File

@@ -89,8 +89,8 @@
await apiCall('database-connections/call-method', { await apiCall('database-connections/call-method', {
conid, conid,
database, database,
method: keyInfo.addMethod, method: keyInfo.keyType.addMethod,
args: [keyInfo.key, ...keyInfo.tableColumns.map(col => row[col.name])], args: [keyInfo.key, ...keyInfo.keyType.dbKeyFields.map(col => row[col.name])],
}); });
refresh(); refresh();
}, },
@@ -114,14 +114,14 @@
{#if keyInfo.type == 'string'} {#if keyInfo.type == 'string'}
<FormStyledButton value="Save" on:click={saveString} disabled={!editedValue} /> <FormStyledButton value="Save" on:click={saveString} disabled={!editedValue} />
{/if} {/if}
{#if keyInfo.addMethod} {#if keyInfo.keyType?.addMethod && keyInfo.keyType?.showItemList}
<FormStyledButton value="Add item" on:click={() => addItem(keyInfo)} /> <FormStyledButton value="Add item" on:click={() => addItem(keyInfo)} />
{/if} {/if}
<FormStyledButton value="Refresh" on:click={refresh} /> <FormStyledButton value="Refresh" on:click={refresh} />
</div> </div>
<div class="content"> <div class="content">
{#if keyInfo.tableColumns} {#if keyInfo.keyType?.dbKeyFields && keyInfo.keyType?.showItemList}
<VerticalSplitter> <VerticalSplitter>
<svelte:fragment slot="1"> <svelte:fragment slot="1">
<DbKeyTableControl <DbKeyTableControl
@@ -134,7 +134,7 @@
/> />
</svelte:fragment> </svelte:fragment>
<svelte:fragment slot="2"> <svelte:fragment slot="2">
<DbKeyItemDetail {keyInfo} item={currentRow} /> <DbKeyItemDetail dbKeyFields={keyInfo.keyType.dbKeyFields} item={currentRow} />
</svelte:fragment> </svelte:fragment>
</VerticalSplitter> </VerticalSplitter>
{:else} {:else}

View File

@@ -1,6 +1,7 @@
<script lang="ts"> <script lang="ts">
import CloseSearchButton from '../buttons/CloseSearchButton.svelte'; import CloseSearchButton from '../buttons/CloseSearchButton.svelte';
import InlineButton from '../buttons/InlineButton.svelte'; import InlineButton from '../buttons/InlineButton.svelte';
import runCommand from '../commands/runCommand';
import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte'; import SearchBoxWrapper from '../elements/SearchBoxWrapper.svelte';
import SearchInput from '../elements/SearchInput.svelte'; import SearchInput from '../elements/SearchInput.svelte';
@@ -20,6 +21,9 @@
<SearchBoxWrapper> <SearchBoxWrapper>
<SearchInput placeholder="Search keys" bind:value={filter} /> <SearchInput placeholder="Search keys" bind:value={filter} />
<CloseSearchButton bind:filter /> <CloseSearchButton bind:filter />
<InlineButton on:click={() => runCommand('new.dbKey')} title="Add new key">
<FontIcon icon="icon plus-thick" />
</InlineButton>
<InlineButton on:click={handleRefreshDatabase} title="Refresh key list"> <InlineButton on:click={handleRefreshDatabase} title="Refresh key list">
<FontIcon icon="icon refresh" /> <FontIcon icon="icon refresh" />
</InlineButton> </InlineButton>

View File

@@ -161,27 +161,29 @@ const driver = {
case 'string': case 'string':
res.value = await pool.get(key); res.value = await pool.get(key);
break; break;
case 'list': // case 'list':
res.tableColumns = [{ name: 'value' }]; // res.tableColumns = [{ name: 'value' }];
res.addMethod = 'rpush'; // res.addMethod = 'rpush';
break; // break;
case 'set': // case 'set':
res.tableColumns = [{ name: 'value' }]; // res.tableColumns = [{ name: 'value' }];
res.keyColumn = 'value'; // res.keyColumn = 'value';
res.addMethod = 'sadd'; // res.addMethod = 'sadd';
break; // break;
case 'zset': // case 'zset':
res.tableColumns = [{ name: 'score' }, { name: 'value' }]; // res.tableColumns = [{ name: 'score' }, { name: 'value' }];
res.keyColumn = 'value'; // res.keyColumn = 'value';
res.addMethod = 'zadd'; // res.addMethod = 'zadd';
break; // break;
case 'hash': // case 'hash':
res.tableColumns = [{ name: 'key' }, { name: 'value' }]; // res.tableColumns = [{ name: 'key' }, { name: 'value' }];
res.keyColumn = 'key'; // res.keyColumn = 'key';
res.addMethod = 'hset'; // res.addMethod = 'hset';
break; // break;
} }
res.keyType = this.supportedKeyTypes.find((x) => x.name == type);
return res; return res;
}, },

View File

@@ -22,6 +22,45 @@ const driver = {
title: 'Redis', title: 'Redis',
defaultPort: 6379, defaultPort: 6379,
databaseEngineTypes: ['keyvalue'], databaseEngineTypes: ['keyvalue'],
supportedKeyTypes: [
{
name: 'string',
label: 'String',
dbKeyFields: [{ name: 'value' }],
addMethod: 'set',
},
{
name: 'list',
label: 'List',
dbKeyFields: [{ name: 'value' }],
addMethod: 'rpush',
showItemList: true,
},
{
name: 'set',
label: 'Set',
dbKeyFields: [{ name: 'value' }],
keyColumn: 'value',
addMethod: 'sadd',
showItemList: true,
},
{
name: 'zset',
label: 'Sorted Set',
dbKeyFields: [{ name: 'score' }, { name: 'value' }],
keyColumn: 'value',
addMethod: 'zadd',
showItemList: true,
},
{
name: 'hash',
label: 'Hash',
dbKeyFields: [{ name: 'key' }, { name: 'value' }],
keyColumn: 'key',
addMethod: 'hset',
showItemList: true,
},
],
showConnectionField: (field, values) => { showConnectionField: (field, values) => {
return ['server', 'port', 'password'].includes(field); return ['server', 'port', 'password'].includes(field);