mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-23 21:56:00 +00:00
new collection modal refactor
This commit is contained in:
6
packages/types/engines.d.ts
vendored
6
packages/types/engines.d.ts
vendored
@@ -2,7 +2,7 @@ import stream from 'stream';
|
|||||||
import { QueryResult } from './query';
|
import { QueryResult } from './query';
|
||||||
import { SqlDialect } from './dialect';
|
import { SqlDialect } from './dialect';
|
||||||
import { SqlDumper } from './dumper';
|
import { SqlDumper } from './dumper';
|
||||||
import { DatabaseInfo, NamedObjectInfo, TableInfo, ViewInfo, ProcedureInfo, FunctionInfo, TriggerInfo } from './dbinfo';
|
import { DatabaseInfo, NamedObjectInfo, TableInfo, ViewInfo, ProcedureInfo, FunctionInfo, TriggerInfo, CollectionInfo } from './dbinfo';
|
||||||
import { FilterBehaviour } from './filter-type';
|
import { FilterBehaviour } from './filter-type';
|
||||||
|
|
||||||
export interface StreamOptions {
|
export interface StreamOptions {
|
||||||
@@ -115,6 +115,8 @@ export interface EngineDriver extends FilterBehaviourProvider {
|
|||||||
profilerChartAggregateFunction?: string;
|
profilerChartAggregateFunction?: string;
|
||||||
profilerChartMeasures?: { label: string; field: string }[];
|
profilerChartMeasures?: { label: string; field: string }[];
|
||||||
isElectronOnly?: boolean;
|
isElectronOnly?: boolean;
|
||||||
|
collectionSingularLabel?: string;
|
||||||
|
collectionPluralLabel?: string;
|
||||||
supportedCreateDatabase?: boolean;
|
supportedCreateDatabase?: boolean;
|
||||||
showConnectionField?: (
|
showConnectionField?: (
|
||||||
field: string,
|
field: string,
|
||||||
@@ -163,7 +165,7 @@ export interface EngineDriver extends FilterBehaviourProvider {
|
|||||||
getAuthTypes(): EngineAuthType[];
|
getAuthTypes(): EngineAuthType[];
|
||||||
readCollection(pool: any, options: ReadCollectionOptions): Promise<any>;
|
readCollection(pool: any, options: ReadCollectionOptions): Promise<any>;
|
||||||
updateCollection(pool: any, changeSet: any): Promise<any>;
|
updateCollection(pool: any, changeSet: any): Promise<any>;
|
||||||
getCollectionUpdateScript(changeSet: any): string;
|
getCollectionUpdateScript(changeSet: any, collectionInfo: CollectionInfo): string;
|
||||||
createDatabase(pool: any, name: string): Promise;
|
createDatabase(pool: any, name: string): Promise;
|
||||||
dropDatabase(pool: any, name: string): Promise;
|
dropDatabase(pool: any, name: string): Promise;
|
||||||
getQuerySplitterOptions(usage: 'stream' | 'script' | 'editor'): any;
|
getQuerySplitterOptions(usage: 'stream' | 'script' | 'editor'): any;
|
||||||
|
|||||||
@@ -91,16 +91,14 @@
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleNewCollection = () => {
|
const handleNewCollection = () => {
|
||||||
showModal(InputTextModal, {
|
showModal(NewCollectionModal, {
|
||||||
value: '',
|
driver,
|
||||||
label: 'New collection/container name',
|
onConfirm: async values => {
|
||||||
header: 'Create collection/container',
|
|
||||||
onConfirm: async newCollection => {
|
|
||||||
runOperationOnDatabase(
|
runOperationOnDatabase(
|
||||||
{ conid: connection._id, database: name },
|
{ conid: connection._id, database: name },
|
||||||
{
|
{
|
||||||
type: 'createCollection',
|
type: 'createCollection',
|
||||||
collection: newCollection,
|
collection: values,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -294,7 +292,10 @@
|
|||||||
return [
|
return [
|
||||||
{ onClick: handleNewQuery, text: 'New query', isNewQuery: true },
|
{ onClick: handleNewQuery, text: 'New query', isNewQuery: true },
|
||||||
driver?.databaseEngineTypes?.includes('sql') && { onClick: handleNewTable, text: 'New table' },
|
driver?.databaseEngineTypes?.includes('sql') && { onClick: handleNewTable, text: 'New table' },
|
||||||
driver?.databaseEngineTypes?.includes('document') && { onClick: handleNewCollection, text: 'New collection/container' },
|
driver?.databaseEngineTypes?.includes('document') && {
|
||||||
|
onClick: handleNewCollection,
|
||||||
|
text: `New ${driver?.collectionSingularLabel ?? 'collection/container'}`,
|
||||||
|
},
|
||||||
driver?.databaseEngineTypes?.includes('sql') && { onClick: handleQueryDesigner, text: 'Design query' },
|
driver?.databaseEngineTypes?.includes('sql') && { onClick: handleQueryDesigner, text: 'Design query' },
|
||||||
driver?.databaseEngineTypes?.includes('sql') && {
|
driver?.databaseEngineTypes?.includes('sql') && {
|
||||||
onClick: handleNewPerspective,
|
onClick: handleNewPerspective,
|
||||||
@@ -386,6 +387,7 @@
|
|||||||
import ExportDatabaseDumpModal from '../modals/ExportDatabaseDumpModal.svelte';
|
import ExportDatabaseDumpModal from '../modals/ExportDatabaseDumpModal.svelte';
|
||||||
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
import ConfirmModal from '../modals/ConfirmModal.svelte';
|
||||||
import { closeMultipleTabs } from '../tabpanel/TabsPanel.svelte';
|
import { closeMultipleTabs } from '../tabpanel/TabsPanel.svelte';
|
||||||
|
import NewCollectionModal from '../modals/NewCollectionModal.svelte';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
export let passProps;
|
export let passProps;
|
||||||
|
|||||||
@@ -525,8 +525,8 @@
|
|||||||
copyTextToClipboard(data.pureName);
|
copyTextToClipboard(data.pureName);
|
||||||
} else if (menu.isRenameCollection) {
|
} else if (menu.isRenameCollection) {
|
||||||
showModal(InputTextModal, {
|
showModal(InputTextModal, {
|
||||||
label: 'New collection/container name',
|
label: `New collection/container name`,
|
||||||
header: 'Rename collection/container',
|
header: `Rename collection/container`,
|
||||||
value: data.pureName,
|
value: data.pureName,
|
||||||
onConfirm: async newName => {
|
onConfirm: async newName => {
|
||||||
const dbid = _.pick(data, ['conid', 'database']);
|
const dbid = _.pick(data, ['conid', 'database']);
|
||||||
|
|||||||
@@ -40,6 +40,7 @@ import { doLogout, internalRedirectTo } from '../clientAuth';
|
|||||||
import { disconnectServerConnection } from '../appobj/ConnectionAppObject.svelte';
|
import { disconnectServerConnection } from '../appobj/ConnectionAppObject.svelte';
|
||||||
import UploadErrorModal from '../modals/UploadErrorModal.svelte';
|
import UploadErrorModal from '../modals/UploadErrorModal.svelte';
|
||||||
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
import ErrorMessageModal from '../modals/ErrorMessageModal.svelte';
|
||||||
|
import NewCollectionModal from '../modals/NewCollectionModal.svelte';
|
||||||
|
|
||||||
// function themeCommand(theme: ThemeDefinition) {
|
// function themeCommand(theme: ThemeDefinition) {
|
||||||
// return {
|
// return {
|
||||||
@@ -287,20 +288,19 @@ registerCommand({
|
|||||||
const $currentDatabase = get(currentDatabase);
|
const $currentDatabase = get(currentDatabase);
|
||||||
const connection = _.get($currentDatabase, 'connection') || {};
|
const connection = _.get($currentDatabase, 'connection') || {};
|
||||||
const database = _.get($currentDatabase, 'name');
|
const database = _.get($currentDatabase, 'name');
|
||||||
|
const driver = findEngineDriver(get(currentDatabase)?.connection, getExtensions());
|
||||||
|
|
||||||
const dbid = { conid: connection._id, database };
|
const dbid = { conid: connection._id, database };
|
||||||
|
|
||||||
showModal(InputTextModal, {
|
showModal(NewCollectionModal, {
|
||||||
value: '',
|
driver,
|
||||||
label: 'New collection/container name',
|
onConfirm: async values => {
|
||||||
header: 'Create collection/container',
|
|
||||||
onConfirm: async newCollection => {
|
|
||||||
// await apiCall('database-connections/run-script', { ...dbid, sql: `db.createCollection('${newCollection}')` });
|
// await apiCall('database-connections/run-script', { ...dbid, sql: `db.createCollection('${newCollection}')` });
|
||||||
const resp = await apiCall('database-connections/run-operation', {
|
const resp = await apiCall('database-connections/run-operation', {
|
||||||
...dbid,
|
...dbid,
|
||||||
operation: {
|
operation: {
|
||||||
type: 'createCollection',
|
type: 'createCollection',
|
||||||
collection: newCollection,
|
collection: values,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
32
packages/web/src/modals/NewCollectionModal.svelte
Normal file
32
packages/web/src/modals/NewCollectionModal.svelte
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
import FormStyledButton from '../buttons/FormStyledButton.svelte';
|
||||||
|
|
||||||
|
import FormProvider from '../forms/FormProvider.svelte';
|
||||||
|
import FormSubmit from '../forms/FormSubmit.svelte';
|
||||||
|
import FormTextField from '../forms/FormTextField.svelte';
|
||||||
|
import ModalBase from './ModalBase.svelte';
|
||||||
|
import { closeCurrentModal } from './modalTools';
|
||||||
|
|
||||||
|
export let onConfirm;
|
||||||
|
export let driver;
|
||||||
|
|
||||||
|
const handleSubmit = async values => {
|
||||||
|
closeCurrentModal();
|
||||||
|
onConfirm(values);
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<FormProvider initialValues={{ name: '' }}>
|
||||||
|
<ModalBase {...$$restProps}>
|
||||||
|
<svelte:fragment slot="header">
|
||||||
|
Create {driver?.collectionSingularLabel ?? 'collection/container'}
|
||||||
|
</svelte:fragment>
|
||||||
|
|
||||||
|
<FormTextField label={`New ${driver?.collectionSingularLabel ?? 'collection/container'} name`} name="name" focused />
|
||||||
|
|
||||||
|
<svelte:fragment slot="footer">
|
||||||
|
<FormSubmit value="OK" on:click={e => handleSubmit(e.detail)} />
|
||||||
|
<FormStyledButton type="button" value="Cancel" on:click={closeCurrentModal} />
|
||||||
|
</svelte:fragment>
|
||||||
|
</ModalBase>
|
||||||
|
</FormProvider>
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
export function save() {
|
export function save() {
|
||||||
const json = $changeSetStore?.value;
|
const json = $changeSetStore?.value;
|
||||||
const driver = findEngineDriver($connection, $extensions);
|
const driver = findEngineDriver($connection, $extensions);
|
||||||
const script = driver.getCollectionUpdateScript ? driver.getCollectionUpdateScript(json) : null;
|
const script = driver.getCollectionUpdateScript ? driver.getCollectionUpdateScript(json, $collectionInfo) : null;
|
||||||
if (script) {
|
if (script) {
|
||||||
if (getBoolSettingsValue('skipConfirm.collectionDataSave', false)) {
|
if (getBoolSettingsValue('skipConfirm.collectionDataSave', false)) {
|
||||||
handleConfirmChange(json);
|
handleConfirmChange(json);
|
||||||
|
|||||||
@@ -38,9 +38,9 @@ export function setSelectedTab(tabid) {
|
|||||||
openedTabs.update(tabs => setSelectedTabFunc(tabs, tabid));
|
openedTabs.update(tabs => setSelectedTabFunc(tabs, tabid));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getObjectTypeFieldLabel(objectTypeField) {
|
export function getObjectTypeFieldLabel(objectTypeField, driver?) {
|
||||||
if (objectTypeField == 'matviews') return 'Materialized Views';
|
if (objectTypeField == 'matviews') return 'Materialized Views';
|
||||||
if (objectTypeField == 'collections') return 'Collections/Containers';
|
if (objectTypeField == 'collections') return _.startCase(driver?.collectionPluralLabel) ?? 'Collections/Containers';
|
||||||
return _.startCase(objectTypeField);
|
return _.startCase(objectTypeField);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,9 @@
|
|||||||
</WidgetColumnBarItem>
|
</WidgetColumnBarItem>
|
||||||
|
|
||||||
<WidgetColumnBarItem
|
<WidgetColumnBarItem
|
||||||
title={driver?.databaseEngineTypes?.includes('document') ? 'Collections/containers' : 'Tables, views, functions'}
|
title={driver?.databaseEngineTypes?.includes('document')
|
||||||
|
? driver?.collectionPluralLabel ?? 'Collections/containers'
|
||||||
|
: 'Tables, views, functions'}
|
||||||
name="dbObjects"
|
name="dbObjects"
|
||||||
storageName="dbObjectsWidget"
|
storageName="dbObjectsWidget"
|
||||||
skip={!(
|
skip={!(
|
||||||
|
|||||||
@@ -120,7 +120,9 @@
|
|||||||
{/if}
|
{/if}
|
||||||
{#if driver?.databaseEngineTypes?.includes('document')}
|
{#if driver?.databaseEngineTypes?.includes('document')}
|
||||||
<div class="m-1" />
|
<div class="m-1" />
|
||||||
<InlineButton on:click={() => runCommand('new.collection')}>New collection/container</InlineButton>
|
<InlineButton on:click={() => runCommand('new.collection')}
|
||||||
|
>New {driver?.collectionSingularLabel ?? 'collection/container'}</InlineButton
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</WidgetsInnerContainer>
|
</WidgetsInnerContainer>
|
||||||
{:else}
|
{:else}
|
||||||
@@ -139,7 +141,7 @@
|
|||||||
<AppObjectList
|
<AppObjectList
|
||||||
list={objectList.map(x => ({ ...x, conid, database }))}
|
list={objectList.map(x => ({ ...x, conid, database }))}
|
||||||
module={databaseObjectAppObject}
|
module={databaseObjectAppObject}
|
||||||
groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField)}
|
groupFunc={data => getObjectTypeFieldLabel(data.objectTypeField, driver)}
|
||||||
subItemsComponent={SubColumnParamList}
|
subItemsComponent={SubColumnParamList}
|
||||||
isExpandable={data =>
|
isExpandable={data =>
|
||||||
data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'}
|
data.objectTypeField == 'tables' || data.objectTypeField == 'views' || data.objectTypeField == 'matviews'}
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ const driver = {
|
|||||||
const { type } = operation;
|
const { type } = operation;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'createCollection':
|
case 'createCollection':
|
||||||
await this.script(pool, `db.createCollection('${operation.collection}')`);
|
await this.script(pool, `db.createCollection('${operation.collection.name}')`);
|
||||||
case 'dropOperation':
|
case 'dropOperation':
|
||||||
await this.script(pool, `db.dropCollection('${operation.collection}')`);
|
await this.script(pool, `db.dropCollection('${operation.collection}')`);
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ const driver = {
|
|||||||
{ label: 'Max duration', field: 'maxDuration' },
|
{ label: 'Max duration', field: 'maxDuration' },
|
||||||
],
|
],
|
||||||
databaseUrlPlaceholder: 'e.g. mongodb://username:password@mongodb.mydomain.net/dbname',
|
databaseUrlPlaceholder: 'e.g. mongodb://username:password@mongodb.mydomain.net/dbname',
|
||||||
|
collectionSingularLabel: 'collection',
|
||||||
|
collectionPluralLabel: 'collections',
|
||||||
|
|
||||||
getQuerySplitterOptions: () => mongoSplitterOptions,
|
getQuerySplitterOptions: () => mongoSplitterOptions,
|
||||||
|
|
||||||
@@ -65,7 +67,7 @@ const driver = {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
||||||
getCollectionUpdateScript(changeSet) {
|
getCollectionUpdateScript(changeSet, collectionInfo) {
|
||||||
let res = '';
|
let res = '';
|
||||||
for (const insert of changeSet.inserts) {
|
for (const insert of changeSet.inserts) {
|
||||||
res += `db.${insert.pureName}.insertOne(${jsonStringifyWithObjectId({
|
res += `db.${insert.pureName}.insertOne(${jsonStringifyWithObjectId({
|
||||||
|
|||||||
Reference in New Issue
Block a user