dbeaver/pro#8821 feat: add import settings step (#4506)

* dbeaver/pro#8821 feat: add gql query for import

* dbeaver/cloudbeaver#8821 throw readable exception on import fail

* dbeaver/pro#8821 feat: add import settings step

* dbeaver/pro#8821 refactor: gql types for driver config

* dbeaver/pro#8821 refactor: use connectionKey

* dbeaver/pro#8821 add open New Connection

* dbeaver/pro#8821 feat: add openNewConnection checkbox and replace docs link

* dbeaver/pro#8821 feat: clear onDuplicateKey if useBulk is active

* dbeaver/pro#8821 feat: add titles

* dbeaver/pro#8821 refactor: remove extra checks (not a driver config, always true)

* dbeaver/pro#8821 remove defaultOpenNewConnection from driverConfiguration

* dbeaver/pro#8821 feat: let a user to clear the replace method

* dbeaver/pro#8821 refactor: update open new connection tooltip

* dbeaver/pro#8821 feat: remove checks for settings step

Always show settings steps with at least one option: use new connection

* dbeaver/pro#8821 refactor: simplify dialog's footer

---------

Co-authored-by: Ruslan <pupkinvasya7000@gmail.com>
Co-authored-by: Daria Marutkina <125263541+dariamarutkina@users.noreply.github.com>
Co-authored-by: Ainur <59531286+yagudin10@users.noreply.github.com>
This commit is contained in:
Sychev Andrey
2026-08-11 18:45:36 +02:00
committed by GitHub
co-authored by Ruslan Daria Marutkina Ainur
parent 317750ea7d
commit 5be49b8a7e
22 changed files with 397 additions and 26 deletions
@@ -48,6 +48,8 @@ input DataTransferImportSettings {
useBulkLoad: Boolean
"Use transactions during import"
useTransactions: Boolean
"Open new connection(s) for the import task"
openNewConnection: Boolean
}
input DataTransferImportParameters {
@@ -425,7 +425,7 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
throw new DBWebException("Import is canceled");
}
} catch (DBException e) {
throw new DBWebException("Import failed cause: " + e.getMessage());
throw new DBWebException("Import failed", e);
}
}
}
@@ -446,6 +446,9 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer {
consumerSettings.setUseTransactions(CommonUtils.getBoolean(
settings.get(DTConstants.PROP_USE_TRANSACTIONS),
consumerSettings.isUseTransactions()));
consumerSettings.setOpenNewConnections(CommonUtils.getBoolean(
settings.get(DTConstants.PROP_OPEN_NEW_CONNECTION),
consumerSettings.isOpenNewConnections()));
}
}
@@ -0,0 +1,9 @@
query getConnectionImportDriverConfiguration($projectId: ID, $connectionId: ID!) {
connections: userConnections(projectId: $projectId, id: $connectionId) {
id
projectId
driverConfiguration {
...DriverConfiguration
}
}
}
@@ -0,0 +1,9 @@
fragment DriverConfiguration on DriverConfiguration {
supportedInsertReplaceMethods {
id
name
description
}
supportsBulkLoad
supportsTransactions
}
@@ -23,6 +23,7 @@
},
"dependencies": {
"@cloudbeaver/core-blocks": "workspace:*",
"@cloudbeaver/core-connections": "workspace:*",
"@cloudbeaver/core-di": "workspace:*",
"@cloudbeaver/core-dialogs": "workspace:*",
"@cloudbeaver/core-events": "workspace:*",
@@ -5,6 +5,7 @@
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { createConnectionParam } from '@cloudbeaver/core-connections';
import { Bootstrap, injectable } from '@cloudbeaver/core-di';
import { CommonDialogService, DialogueStateResult } from '@cloudbeaver/core-dialogs';
import { ACTION_IMPORT, ActionService, menuExtractItems, MenuService } from '@cloudbeaver/core-view';
@@ -72,16 +73,20 @@ export class DataImportBootstrap extends Bootstrap {
throw new Error('Execution context must be provided');
}
const { status, result: dialogResult } = await this.commonDialogService.open(DataImportDialogLazy, { tableName: model.name ?? model.id });
const connectionKey = createConnectionParam(executionContext.projectId, executionContext.connectionId);
const { status, result: dialogResult } = await this.commonDialogService.open(DataImportDialogLazy, {
tableName: model.name ?? model.id,
connectionKey,
});
if (status === DialogueStateResult.Resolved && dialogResult) {
const success = await this.dataImportService.importData(
executionContext.connectionId,
connectionKey,
executionContext.id,
executionContext.projectId,
result.id,
dialogResult.processorId,
dialogResult.file,
dialogResult.settings,
);
if (success) {
@@ -1,28 +1,42 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2025 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react-lite';
import { Button, CommonDialogBody, CommonDialogFooter, CommonDialogHeader, CommonDialogWrapper, useTranslate } from '@cloudbeaver/core-blocks';
import {
Button,
CommonDialogBody,
CommonDialogFooter,
CommonDialogHeader,
CommonDialogWrapper,
useResource,
useTranslate,
} from '@cloudbeaver/core-blocks';
import type { IConnectionInfoParams } from '@cloudbeaver/core-connections';
import type { DialogComponent } from '@cloudbeaver/core-dialogs';
import type { DataTransferImportSettings } from '@cloudbeaver/core-sdk';
import { DataImportDriverConfigurationResource } from '../DataImportDriverConfigurationResource.js';
import { DataImportFileSelector } from './DataImportFileSelector.js';
import { EDataImportDialogStep } from './EDataImportDialogStep.js';
import type { IDataImportDialogState } from './IDataImportDialogState.js';
import { ImportProcessorList } from './ImportProcessorList.js';
import { ImportSettingsForm } from './ImportSettingsForm.js';
import { useDataImportDialog } from './useDataImportDialog.js';
export interface IDataImportDialogResult {
file: File;
processorId: string;
settings: DataTransferImportSettings;
}
export interface IDataImportDialogPayload {
tableName: string;
connectionKey: IConnectionInfoParams;
initialState?: IDataImportDialogState;
}
@@ -33,38 +47,52 @@ export const DataImportDialog: DialogComponent<IDataImportDialogPayload, IDataIm
}) {
const translate = useTranslate();
const dialog = useDataImportDialog(payload.initialState);
const driverConfigurationResource = useResource(DataImportDialog, DataImportDriverConfigurationResource, payload.connectionKey, { silent: true });
const driverConfiguration = driverConfigurationResource.tryGetData ?? null;
const isSettingsStep = dialog.state.step === EDataImportDialogStep.Settings;
let title = translate('plugin_data_import_title');
let icon = '/icons/data-import.svg';
if (dialog.state.step === EDataImportDialogStep.File && dialog.state.selectedProcessor) {
if (dialog.state.step !== EDataImportDialogStep.Processor && dialog.state.selectedProcessor) {
title += ` (${dialog.state.selectedProcessor.name ?? dialog.state.selectedProcessor.id})`;
icon = dialog.state.selectedProcessor.icon ?? icon;
}
function importData() {
if (dialog.state.file && dialog.state.selectedProcessor) {
resolveDialog({ file: dialog.state.file, processorId: dialog.state.selectedProcessor.id, settings: dialog.state.settings });
}
}
return (
<CommonDialogWrapper size="large" fixedSize>
<CommonDialogHeader title={title} subTitle={payload.tableName} icon={icon} onReject={rejectDialog} />
<CommonDialogBody noBodyPadding>
{dialog.state.step === EDataImportDialogStep.Processor && <ImportProcessorList onSelect={dialog.selectProcessor} />}
{dialog.state.step === EDataImportDialogStep.File && <DataImportFileSelector state={dialog.state} onDelete={dialog.deleteFile} />}
{dialog.state.step === EDataImportDialogStep.Settings && driverConfiguration && (
<ImportSettingsForm settings={dialog.state.settings} driverConfiguration={driverConfiguration} />
)}
</CommonDialogBody>
<CommonDialogFooter>
<Button type="button" variant="secondary" onClick={() => rejectDialog()}>
{translate('ui_processing_cancel')}
</Button>
{dialog.state.step === EDataImportDialogStep.File && (
{dialog.state.step !== EDataImportDialogStep.Processor && (
<div className="tw:flex tw:ml-auto tw:gap-2">
<Button type="button" variant="secondary" onClick={dialog.stepBack}>
{translate('ui_stepper_back')}
</Button>
<Button
type="button"
loading={driverConfigurationResource.isLoading()}
disabled={!dialog.state.file || !dialog.state.selectedProcessor}
onClick={() => resolveDialog({ file: dialog.state.file!, processorId: dialog.state.selectedProcessor!.id })}
onClick={isSettingsStep ? importData : () => dialog.goToSettings(driverConfiguration)}
>
{translate('ui_import')}
{translate(isSettingsStep ? 'ui_import' : 'ui_stepper_next')}
</Button>
</div>
)}
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -8,4 +8,5 @@
export enum EDataImportDialogStep {
Processor,
File,
Settings,
}
@@ -1,11 +1,11 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import type { DataTransferProcessorInfo } from '@cloudbeaver/core-sdk';
import type { DataTransferImportSettings, DataTransferProcessorInfo } from '@cloudbeaver/core-sdk';
import type { EDataImportDialogStep } from './EDataImportDialogStep.js';
@@ -13,4 +13,5 @@ export interface IDataImportDialogState {
step: EDataImportDialogStep;
file: File | null;
selectedProcessor: DataTransferProcessorInfo | null;
settings: DataTransferImportSettings;
}
@@ -0,0 +1,72 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { observer } from 'mobx-react-lite';
import { useEffect } from 'react';
import { Combobox, Container, FieldCheckbox, Link, useTranslate } from '@cloudbeaver/core-blocks';
import type { DataTransferImportSettings } from '@cloudbeaver/core-sdk';
import type { IDataImportDriverConfiguration } from '../DataImportDriverConfigurationResource.js';
interface Props {
settings: DataTransferImportSettings;
driverConfiguration: IDataImportDriverConfiguration;
}
export const ImportSettingsForm = observer<Props>(function ImportSettingsForm({ settings, driverConfiguration }) {
const translate = useTranslate();
const { supportedInsertReplaceMethods, supportsBulkLoad, supportsTransactions } = driverConfiguration;
useEffect(() => {
if (settings.useBulkLoad) {
settings.onDuplicateKeyMethod = undefined;
}
}, [settings.useBulkLoad]);
return (
<Container gap parent>
{supportedInsertReplaceMethods.length > 0 && (
<div>
<Combobox
name="onDuplicateKeyMethod"
state={settings}
items={supportedInsertReplaceMethods}
keySelector={method => method.id}
valueSelector={method => method.name}
titleSelector={method => method.description ?? undefined}
disabled={settings.useBulkLoad}
title={translate('plugin_data_import_settings_on_duplicate_key_title')}
placeholder={translate('plugin_data_import_settings_on_duplicate_key_placeholder')}
allowClear
>
{translate('plugin_data_import_settings_on_duplicate_key')}
</Combobox>
<Link className="tw:text-xs" href="https://dbeaver.com/docs/cloudbeaver/Data-Import-and-Replace/" target="_blank">
{translate('plugin_data_import_settings_on_duplicate_key_help')}
</Link>
</div>
)}
<Container vertical>
{supportsBulkLoad && (
<FieldCheckbox title={translate('plugin_data_import_settings_use_bulk_load_title')} name="useBulkLoad" state={settings}>
{translate('plugin_data_import_settings_use_bulk_load')}
</FieldCheckbox>
)}
{supportsTransactions && (
<FieldCheckbox title={translate('plugin_data_import_settings_use_transactions_title')} name="useTransactions" state={settings}>
{translate('plugin_data_import_settings_use_transactions')}
</FieldCheckbox>
)}
<FieldCheckbox title={translate('plugin_data_import_settings_open_new_connection_title')} name="openNewConnection" state={settings}>
{translate('plugin_data_import_settings_open_new_connection')}
</FieldCheckbox>
</Container>
</Container>
);
});
@@ -1,6 +1,6 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2024 DBeaver Corp and others
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
@@ -8,14 +8,16 @@
import { action, observable } from 'mobx';
import { useObservableRef } from '@cloudbeaver/core-blocks';
import type { DataTransferProcessorInfo } from '@cloudbeaver/core-sdk';
import type { DataTransferImportSettings, DataTransferProcessorInfo } from '@cloudbeaver/core-sdk';
import type { IDataImportDriverConfiguration } from '../DataImportDriverConfigurationResource.js';
import { EDataImportDialogStep } from './EDataImportDialogStep.js';
import type { IDataImportDialogState } from './IDataImportDialogState.js';
interface IDialog {
state: IDataImportDialogState;
stepBack: () => void;
goToSettings: (configuration: IDataImportDriverConfiguration | null) => void;
selectProcessor: (processor: DataTransferProcessorInfo) => void;
deleteFile: () => void;
reset: () => void;
@@ -25,17 +27,46 @@ const DEFAULT_STATE_GETTER: () => IDataImportDialogState = () => ({
step: EDataImportDialogStep.Processor,
file: null,
selectedProcessor: null,
settings: {},
});
export function useDataImportDialog(initialState?: IDataImportDialogState) {
const dialog = useObservableRef<IDialog>(
function getDefaultSettings(configuration: IDataImportDriverConfiguration): DataTransferImportSettings {
const settings: DataTransferImportSettings = {
openNewConnection: true,
};
if (configuration.supportsTransactions) {
settings.useTransactions = true;
}
if (configuration.supportedInsertReplaceMethods) {
settings.onDuplicateKeyMethod = undefined;
}
if (configuration.supportsBulkLoad) {
settings.useBulkLoad = false;
}
return settings;
}
export function useDataImportDialog(initialState?: IDataImportDialogState): IDialog {
return useObservableRef<IDialog>(
() => ({
state: initialState ?? DEFAULT_STATE_GETTER(),
stepBack() {
if (this.state.step === EDataImportDialogStep.File) {
if (this.state.step === EDataImportDialogStep.Settings) {
this.state.step = EDataImportDialogStep.File;
} else if (this.state.step === EDataImportDialogStep.File) {
this.state.step = EDataImportDialogStep.Processor;
}
},
goToSettings(configuration: IDataImportDriverConfiguration | null) {
if (configuration) {
this.state.settings = { ...getDefaultSettings(configuration), ...this.state.settings };
}
this.state.step = EDataImportDialogStep.Settings;
},
selectProcessor(processor: DataTransferProcessorInfo) {
if (this.state.selectedProcessor && this.state.selectedProcessor.id !== processor.id) {
this.reset();
@@ -51,9 +82,14 @@ export function useDataImportDialog(initialState?: IDataImportDialogState) {
this.state = DEFAULT_STATE_GETTER();
},
}),
{ state: observable, stepBack: action.bound, selectProcessor: action.bound, deleteFile: action.bound, reset: action.bound },
{
state: observable,
stepBack: action.bound,
goToSettings: action.bound,
selectProcessor: action.bound,
deleteFile: action.bound,
reset: action.bound,
},
false,
);
return dialog;
}
@@ -0,0 +1,79 @@
/*
* CloudBeaver - Cloud Database Manager
* Copyright (C) 2020-2026 DBeaver Corp and others
*
* Licensed under the Apache License, Version 2.0.
* you may not use this file except in compliance with the License.
*/
import { toJS } from 'mobx';
import {
CONNECTION_INFO_PARAM_SCHEMA,
ConnectionInfoResource,
createConnectionParam,
type IConnectionInfoParams,
isConnectionInfoParamEqual,
} from '@cloudbeaver/core-connections';
import { injectable } from '@cloudbeaver/core-di';
import { CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource';
import { type DriverConfigurationFragment, type GetConnectionImportDriverConfigurationQuery, GraphQLService } from '@cloudbeaver/core-sdk';
import { schemaValidationError } from '@cloudbeaver/core-utils';
export type IDataImportDriverConfiguration = DriverConfigurationFragment;
@injectable(() => [GraphQLService, ConnectionInfoResource])
export class DataImportDriverConfigurationResource extends CachedMapResource<IConnectionInfoParams, IDataImportDriverConfiguration> {
constructor(
private readonly graphQLService: GraphQLService,
private readonly connectionInfoResource: ConnectionInfoResource,
) {
super();
this.sync(connectionInfoResource);
connectionInfoResource.onItemDelete.addHandler(this.delete.bind(this));
}
override isKeyEqual(param: IConnectionInfoParams, second: IConnectionInfoParams): boolean {
return isConnectionInfoParamEqual(param, second);
}
protected async loader(originalKey: ResourceKey<IConnectionInfoParams>): Promise<Map<IConnectionInfoParams, IDataImportDriverConfiguration>> {
if (isResourceAlias(originalKey)) {
throw new Error('Aliases are not supported by this resource');
}
const connectionsList: GetConnectionImportDriverConfigurationQuery['connections'] = [];
await ResourceKeyUtils.forEachAsync(originalKey, async key => {
if (!this.connectionInfoResource.isConnected(key)) {
throw new Error(`Connection is not connected (${key.projectId}, ${key.connectionId})`);
}
const { connections } = await this.graphQLService.sdk.getConnectionImportDriverConfiguration({
projectId: key.projectId,
connectionId: key.connectionId,
});
if (!connections.some(connection => connection.id === key.connectionId)) {
throw new Error(`Connection is not found (${key.connectionId})`);
}
connectionsList.push(...connections);
});
this.set(
resourceKeyList(connectionsList.map(createConnectionParam)),
connectionsList.map(connection => connection.driverConfiguration),
);
return this.data;
}
protected validateKey(key: IConnectionInfoParams): boolean {
const parse = CONNECTION_INFO_PARAM_SCHEMA.safeParse(toJS(key));
if (!parse.success) {
this.logger.warn(`Invalid resource key ${schemaValidationError(parse.error).toString()}`);
}
return parse.success;
}
}
@@ -8,10 +8,11 @@
import { computed, makeObservable } from 'mobx';
import { ProcessSnackbar } from '@cloudbeaver/core-blocks';
import type { IConnectionInfoParams } from '@cloudbeaver/core-connections';
import { injectable } from '@cloudbeaver/core-di';
import { NotificationService } from '@cloudbeaver/core-events';
import { AsyncTaskInfoService, EAdminPermission, SessionPermissionsResource } from '@cloudbeaver/core-root';
import { GraphQLService } from '@cloudbeaver/core-sdk';
import { type DataTransferImportSettings, GraphQLService } from '@cloudbeaver/core-sdk';
import { getProgressPercent } from '@cloudbeaver/core-utils';
import { DataImportSettingsService } from './DataImportSettingsService.js';
@@ -38,7 +39,14 @@ export class DataImportService {
});
}
async importData(connectionId: string, contextId: string, projectId: string, resultsId: string, processorId: string, file: File): Promise<boolean> {
async importData(
connectionKey: IConnectionInfoParams,
contextId: string,
resultsId: string,
processorId: string,
file: File,
settings?: DataTransferImportSettings,
): Promise<boolean> {
const abortController = new AbortController();
let cancelImplementation: (() => void | Promise<void>) | null;
let isCancelled = false;
@@ -65,11 +73,11 @@ export class DataImportService {
const { taskInfo } = await this.graphQLService.sdk.dataTransferImportDataIntoResults(
{
connectionId,
contextId,
projectId,
connectionId: connectionKey.connectionId,
projectId: connectionKey.projectId,
resultsId,
parameters: { processorId },
parameters: { processorId, settings },
},
undefined,
abortController.signal,
@@ -4,4 +4,24 @@ export default [
['plugin_data_import_process_success', 'Data imported successfully'],
['plugin_data_import_process_fail', 'Data import failed'],
['plugin_data_import_process_file_processing_step_message', 'File uploaded, processing...'],
['plugin_data_import_settings_on_duplicate_key', 'On duplicate key'],
['plugin_data_import_settings_use_bulk_load', 'Use bulk load'],
['plugin_data_import_settings_use_bulk_load_title', 'Use bulk load for faster import'],
['plugin_data_import_settings_use_transactions', 'Use transactions'],
[
'plugin_data_import_settings_use_transactions_title',
'Execute the import within a database transaction. If the import fails, all changes can be rolled back',
],
[
'plugin_data_import_settings_on_duplicate_key_title',
'Choose how to handle rows that already exist in the target table based on a primary or unique key',
],
['plugin_data_import_settings_on_duplicate_key_placeholder', 'None'],
['plugin_data_import_settings_open_new_connection', 'Open new connection'],
[
'plugin_data_import_settings_open_new_connection_title',
'Use this option to speed up data transfer. If selected, a new connection will be opened and the data transfer will not interfere with other calls to the database where data is being transferred to.',
],
['plugin_data_import_settings_on_duplicate_key_help', 'Learn more about the "On duplicate key" setting'],
];
@@ -4,4 +4,23 @@ export default [
['plugin_data_import_process_success', 'Données importées avec succès'],
['plugin_data_import_process_fail', "Échec de l'importation des données"],
['plugin_data_import_process_file_processing_step_message', 'Fichier téléchargé, en cours de traitement...'],
['plugin_data_import_settings_on_duplicate_key', 'En cas de clé dupliquée'],
[
'plugin_data_import_settings_on_duplicate_key_title',
"Choisissez comment gérer les lignes qui existent déjà dans la table cible en fonction d'une clé primaire ou unique",
],
['plugin_data_import_settings_use_bulk_load_title', 'Utiliser le chargement en masse pour un import plus rapide'],
['plugin_data_import_settings_use_bulk_load', 'Utiliser le chargement en masse'],
['plugin_data_import_settings_use_transactions', 'Utiliser les transactions'],
[
'plugin_data_import_settings_use_transactions_title',
"Exécuter l'importation dans une transaction de base de données. Si l'importation échoue, toutes les modifications peuvent être annulées",
],
['plugin_data_import_settings_on_duplicate_key_placeholder', 'Aucune'],
['plugin_data_import_settings_open_new_connection', 'Ouvrir une nouvelle connexion'],
[
'plugin_data_import_settings_open_new_connection_title',
"Utilisez cette option pour accélérer le transfert de données. Si elle est sélectionnée, une nouvelle connexion sera ouverte et le transfert de données n'interférera pas avec les autres appels à la base de données vers laquelle les données sont transférées.",
],
['plugin_data_import_settings_on_duplicate_key_help', 'En savoir plus sur le paramètre "En cas de clé dupliquée"'],
];
@@ -4,4 +4,24 @@ export default [
['plugin_data_import_process_success', 'Data imported successfully'],
['plugin_data_import_process_fail', 'Data import failed'],
['plugin_data_import_process_file_processing_step_message', 'File uploaded, processing...'],
['plugin_data_import_settings_on_duplicate_key', 'On duplicate key'],
['plugin_data_import_settings_use_bulk_load', 'Use bulk load'],
['plugin_data_import_settings_use_bulk_load_title', 'Use bulk load for faster import'],
['plugin_data_import_settings_use_transactions', 'Use transactions'],
[
'plugin_data_import_settings_use_transactions_title',
'Execute the import within a database transaction. If the import fails, all changes can be rolled back',
],
[
'plugin_data_import_settings_on_duplicate_key_title',
'Choose how to handle rows that already exist in the target table based on a primary or unique key',
],
['plugin_data_import_settings_on_duplicate_key_placeholder', 'None'],
['plugin_data_import_settings_open_new_connection', 'Open new connection'],
[
'plugin_data_import_settings_open_new_connection_title',
'Use this option to speed up data transfer. If selected, a new connection will be opened and the data transfer will not interfere with other calls to the database where data is being transferred to',
],
['plugin_data_import_settings_on_duplicate_key_help', 'Learn more about the "On duplicate key" setting'],
];
@@ -4,4 +4,24 @@ export default [
['plugin_data_import_process_success', 'Данные успешно импортированы'],
['plugin_data_import_process_fail', 'Ошибка импорта данных'],
['plugin_data_import_process_file_processing_step_message', 'Файл загружен, обработка...'],
['plugin_data_import_settings_on_duplicate_key', 'При дублировании ключа'],
[
'plugin_data_import_settings_on_duplicate_key_title',
'Выберите, как обрабатывать строки, которые уже существуют в целевой таблице на основе первичного или уникального ключа',
],
['plugin_data_import_settings_use_bulk_load', 'Использовать массовую загрузку'],
['plugin_data_import_settings_use_bulk_load_title', 'Использовать массовую загрузку для более быстрого импорта'],
['plugin_data_import_settings_use_transactions', 'Использовать транзакции'],
[
'plugin_data_import_settings_use_transactions_title',
'Выполнять импорт в рамках транзакции базы данных. Если импорт не удается, все изменения могут быть отменены',
],
['plugin_data_import_settings_on_duplicate_key_placeholder', 'Нет'],
['plugin_data_import_settings_open_new_connection', 'Открыть новое соединение'],
[
'plugin_data_import_settings_open_new_connection_title',
'Используйте эту опцию, чтобы ускорить передачу данных. Если выбран этот параметр, будет открыто новое соединение, и передача данных не будет мешать другим вызовам к базе данных, в которую передаются данные',
],
['plugin_data_import_settings_on_duplicate_key_help', 'Узнать больше о параметре "При дублировании ключа"'],
];
@@ -4,4 +4,23 @@ export default [
['plugin_data_import_process_success', 'Dữ liệu đã được nhập thành công'],
['plugin_data_import_process_fail', 'Nhập dữ liệu thất bại'],
['plugin_data_import_process_file_processing_step_message', 'Tệp đã được tải lên, đang xử lý...'],
['plugin_data_import_settings_on_duplicate_key', 'Khi trùng lặp khóa'],
[
'plugin_data_import_settings_on_duplicate_key_title',
'Chọn cách xử lý các hàng đã tồn tại trong bảng đích dựa trên khóa chính hoặc khóa duy nhất',
],
['plugin_data_import_settings_use_bulk_load', 'Sử dụng tải hàng loạt'],
['plugin_data_import_settings_use_bulk_load_title', 'Sử dụng tải hàng loạt để nhập nhanh hơn'],
['plugin_data_import_settings_use_transactions', 'Sử dụng giao dịch'],
[
'plugin_data_import_settings_use_transactions_title',
'Thực hiện nhập trong một giao dịch cơ sở dữ liệu. Nếu nhập thất bại, tất cả các thay đổi có thể được hoàn tác',
],
['plugin_data_import_settings_on_duplicate_key_placeholder', 'Không có'],
['plugin_data_import_settings_open_new_connection', 'Mở kết nối mới'],
[
'plugin_data_import_settings_open_new_connection_title',
'Sử dụng tùy chọn này để tăng tốc độ truyền dữ liệu. Nếu được chọn, một kết nối mới sẽ được mở và việc truyền dữ liệu sẽ không ảnh hưởng đến các cuộc gọi khác đến cơ sở dữ liệu nơi dữ liệu đang được truyền đến',
],
['plugin_data_import_settings_on_duplicate_key_help', 'Tìm hiểu thêm về cài đặt "Khi trùng lặp khóa"'],
];
@@ -4,4 +4,17 @@ export default [
['plugin_data_import_process_success', '数据导入成功'],
['plugin_data_import_process_fail', '数据导入失败'],
['plugin_data_import_process_file_processing_step_message', '文件已上传,正在处理...'],
['plugin_data_import_settings_on_duplicate_key', '当重复键时'],
['plugin_data_import_settings_on_duplicate_key_title', '选择如何处理目标表中已存在的行,基于主键或唯一键'],
['plugin_data_import_settings_use_bulk_load', '使用批量加载'],
['plugin_data_import_settings_use_bulk_load_title', '使用批量加载以更快地导入数据'],
['plugin_data_import_settings_use_transactions', '使用事务'],
['plugin_data_import_settings_use_transactions_title', '在数据库事务中执行导入。如果导入失败,所有更改都可以回滚'],
['plugin_data_import_settings_on_duplicate_key_placeholder', '无'],
['plugin_data_import_settings_open_new_connection', '打开新连接'],
[
'plugin_data_import_settings_open_new_connection_title',
'使用此选项可加快数据传输。如果选中,将打开一个新连接,数据传输不会干扰对目标数据库的其他调用。',
],
['plugin_data_import_settings_on_duplicate_key_help', '了解有关“当重复键时”设置的更多信息'],
];
@@ -10,6 +10,7 @@ import { Dependency, ModuleRegistry, proxy, Bootstrap } from '@cloudbeaver/core-
import { LocaleService } from './LocaleService.js';
import { DataImportService } from './DataImportService.js';
import { DataImportProcessorsResource } from './DataImportProcessorsResource.js';
import { DataImportDriverConfigurationResource } from './DataImportDriverConfigurationResource.js';
import { DataImportSettingsService } from './DataImportSettingsService.js';
import { DataImportBootstrap } from './DataImportBootstrap.js';
@@ -25,6 +26,7 @@ export default ModuleRegistry.add({
.addSingleton(Bootstrap, LocaleService)
.addSingleton(DataImportService)
.addSingleton(DataImportProcessorsResource)
.addSingleton(DataImportDriverConfigurationResource)
.addSingleton(DataImportSettingsService);
},
});
@@ -16,6 +16,9 @@
{
"path": "../core-cli"
},
{
"path": "../core-connections"
},
{
"path": "../core-di"
},
+1
View File
@@ -3176,6 +3176,7 @@ __metadata:
dependencies:
"@cloudbeaver/core-blocks": "workspace:*"
"@cloudbeaver/core-cli": "workspace:*"
"@cloudbeaver/core-connections": "workspace:*"
"@cloudbeaver/core-di": "workspace:*"
"@cloudbeaver/core-dialogs": "workspace:*"
"@cloudbeaver/core-events": "workspace:*"