diff --git a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java index 8aabe975f3..f2000e8d37 100644 --- a/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java +++ b/server/bundles/io.cloudbeaver.server/src/io/cloudbeaver/server/CBPlatform.java @@ -293,16 +293,20 @@ public class CBPlatform extends BasePlatformImpl { if (!WebDriverRegistry.getInstance().isDriverEnabled(driver)) { continue; } - boolean hasAllFiles = true; + boolean hasAllFiles = true, hasJars = false; for (DBPDriverLibrary lib : libraries) { if (!lib.isOptional() && lib.getType() != DBPDriverLibrary.FileType.license && - (lib.getLocalFile() == null || !Files.exists(lib.getLocalFile()))) { + (lib.getLocalFile() == null || !Files.exists(lib.getLocalFile()))) + { hasAllFiles = false; log.error("\tDriver '" + driver.getId() + "' is missing library '" + lib.getDisplayName() + "'"); - break; + } else { + if (lib.getType() == DBPDriverLibrary.FileType.jar) { + hasJars = true; + } } } - if (hasAllFiles) { + if (hasAllFiles || hasJars) { applicableDrivers.add(driver); } } diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/schema/service.data.transfer.graphqls b/server/bundles/io.cloudbeaver.service.data.transfer/schema/service.data.transfer.graphqls index f4ee2c59a5..aa3753cf01 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/schema/service.data.transfer.graphqls +++ b/server/bundles/io.cloudbeaver.service.data.transfer/schema/service.data.transfer.graphqls @@ -14,6 +14,23 @@ type DataTransferProcessorInfo { isHTML: Boolean } +input DataTransferOutputSettingsInput { + insertBom: Boolean + encoding: String + timestampPattern: String +} + +type DataTransferOutputSettings { + insertBom: Boolean! + encoding: String! + timestampPattern: String! +} + +type DataTransferDefaultExportSettings { + outputSettings : DataTransferOutputSettings! + supportedEncodings: [String!]! +} + input DataTransferParameters { # Processor ID processorId: ID! @@ -22,6 +39,8 @@ input DataTransferParameters { settings: Object # Processor properties. See DataTransferProcessorInfo.properties processorProperties: Object! + # Consumer properties. See StreamConsumerSettings + outputSettings: DataTransferOutputSettingsInput # Data filter settings filter: SQLDataFilter } @@ -31,6 +50,8 @@ extend type Query { # Available transfer processors dataTransferAvailableStreamProcessors: [ DataTransferProcessorInfo! ]! + dataTransferDefaultExportSettings: DataTransferDefaultExportSettings! + dataTransferExportDataFromContainer( projectId: ID, connectionId: ID!, diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/DBWServiceDataTransfer.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/DBWServiceDataTransfer.java index 813433facc..4f158e3cc0 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/DBWServiceDataTransfer.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/DBWServiceDataTransfer.java @@ -21,6 +21,7 @@ import io.cloudbeaver.DBWebException; import io.cloudbeaver.WebAction; import io.cloudbeaver.model.WebAsyncTaskInfo; import io.cloudbeaver.model.session.WebSession; +import io.cloudbeaver.service.data.transfer.impl.WebDataTransferDefaultExportSettings; import io.cloudbeaver.service.data.transfer.impl.WebDataTransferParameters; import io.cloudbeaver.service.data.transfer.impl.WebDataTransferStreamProcessor; import io.cloudbeaver.service.sql.WebSQLContextInfo; @@ -51,4 +52,5 @@ public interface DBWServiceDataTransfer extends DBWService { @WebAction Boolean dataTransferRemoveDataFile(WebSession session, String dataFileId) throws DBWebException; + WebDataTransferDefaultExportSettings defaultExportSettings(); } diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/WebServiceBindingDataTransfer.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/WebServiceBindingDataTransfer.java index 2a552c9138..c87a5ad872 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/WebServiceBindingDataTransfer.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/WebServiceBindingDataTransfer.java @@ -56,6 +56,7 @@ public class WebServiceBindingDataTransfer extends WebServiceBindingBase getService(env).defaultExportSettings()) ; } diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferDefaultExportSettings.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferDefaultExportSettings.java new file mode 100644 index 0000000000..5e9435998c --- /dev/null +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferDefaultExportSettings.java @@ -0,0 +1,45 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver.service.data.transfer.impl; + +import org.jkiss.dbeaver.tools.transfer.stream.StreamConsumerSettings; + +import java.nio.charset.Charset; +import java.util.Set; + +public class WebDataTransferDefaultExportSettings { + private final WebDataTransferOutputSettings outputSettings; + private final Set supportedEncodings; + + public WebDataTransferDefaultExportSettings() { + var defConsumerSettings = new StreamConsumerSettings(); + this.outputSettings = new WebDataTransferOutputSettings( + false, + defConsumerSettings.getOutputEncoding(), + defConsumerSettings.getOutputTimestampPattern() + ); + this.supportedEncodings = Charset.availableCharsets().keySet(); + } + + public WebDataTransferOutputSettings getOutputSettings() { + return outputSettings; + } + + public Set getSupportedEncodings() { + return supportedEncodings; + } +} diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferOutputSettings.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferOutputSettings.java new file mode 100644 index 0000000000..b38596e936 --- /dev/null +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferOutputSettings.java @@ -0,0 +1,51 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.cloudbeaver.service.data.transfer.impl; + +import org.jkiss.dbeaver.model.data.json.JSONUtils; + +import java.util.Map; + +public class WebDataTransferOutputSettings { + private final boolean insertBom; + private final String encoding; + private final String timestampPattern; + + public WebDataTransferOutputSettings(Map outputSettings) { + this.insertBom = JSONUtils.getBoolean(outputSettings, "insertBom", false); + this.encoding = JSONUtils.getString(outputSettings, "encoding"); + this.timestampPattern = JSONUtils.getString(outputSettings, "timestampPattern"); + } + + public WebDataTransferOutputSettings(boolean insertBom, String encoding, String timestampPattern) { + this.insertBom = insertBom; + this.encoding = encoding; + this.timestampPattern = timestampPattern; + } + + public boolean isInsertBom() { + return insertBom; + } + + public String getEncoding() { + return encoding; + } + + public String getTimestampPattern() { + return timestampPattern; + } +} diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferParameters.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferParameters.java index d04362dbac..f257b395b1 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferParameters.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferParameters.java @@ -1,3 +1,19 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.cloudbeaver.service.data.transfer.impl; import io.cloudbeaver.service.sql.WebSQLDataFilter; @@ -8,18 +24,20 @@ import java.util.Map; public class WebDataTransferParameters { private String processorId; - private Map settings; + private Map dbProducerSettings; private Map processorProperties; private WebSQLDataFilter filter; + private WebDataTransferOutputSettings outputSettings; public WebDataTransferParameters() { } public WebDataTransferParameters(Map params) { this.processorId = JSONUtils.getString(params, "processorId"); - this.settings = JSONUtils.getObject(params, "settings"); + this.dbProducerSettings = JSONUtils.getObject(params, "settings"); this.processorProperties = JSONUtils.getObject(params, "processorProperties"); this.filter = new WebSQLDataFilter(JSONUtils.getObject(params, "filter")); + this.outputSettings = new WebDataTransferOutputSettings(JSONUtils.getObject(params, "outputSettings")); } public String getProcessorId() { @@ -30,12 +48,12 @@ public class WebDataTransferParameters { this.processorId = processorId; } - public Map getSettings() { - return settings; + public Map getDbProducerSettings() { + return dbProducerSettings; } - public void setSettings(Map settings) { - this.settings = settings; + public void setDbProducerSettings(Map dbProducerSettings) { + this.dbProducerSettings = dbProducerSettings; } public Map getProcessorProperties() { @@ -53,4 +71,8 @@ public class WebDataTransferParameters { public void setFilter(WebSQLDataFilter filter) { this.filter = filter; } + + public WebDataTransferOutputSettings getOutputSettings() { + return outputSettings; + } } \ No newline at end of file diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java index 623be196df..5cbd178ea9 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferServlet.java @@ -1,3 +1,19 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.cloudbeaver.service.data.transfer.impl; import io.cloudbeaver.DBWebException; diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferSessionConfig.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferSessionConfig.java index 6b784471d2..e6e83ea5ff 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferSessionConfig.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferSessionConfig.java @@ -1,3 +1,19 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.cloudbeaver.service.data.transfer.impl; import java.util.HashMap; diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferStreamProcessor.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferStreamProcessor.java index 89a676d703..8f550113c5 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferStreamProcessor.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferStreamProcessor.java @@ -1,3 +1,19 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.cloudbeaver.service.data.transfer.impl; import io.cloudbeaver.model.WebPropertyInfo; diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java index c56f0c73c2..89fd7521b1 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferTaskConfig.java @@ -1,3 +1,19 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.cloudbeaver.service.data.transfer.impl; import org.jkiss.dbeaver.Log; diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java index 40641112cf..d160307c56 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebDataTransferUtils.java @@ -1,3 +1,19 @@ +/* + * DBeaver - Universal Database Manager + * Copyright (C) 2010-2022 DBeaver Corp and others + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package io.cloudbeaver.service.data.transfer.impl; import io.cloudbeaver.model.session.WebSession; diff --git a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java index 81fc63357f..42bf3dfb54 100644 --- a/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java +++ b/server/bundles/io.cloudbeaver.service.data.transfer/src/io/cloudbeaver/service/data/transfer/impl/WebServiceDataTransfer.java @@ -142,6 +142,11 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { return true; } + @Override + public WebDataTransferDefaultExportSettings defaultExportSettings() { + return new WebDataTransferDefaultExportSettings(); + } + private WebAsyncTaskInfo asyncExportFromDataContainer(WebSQLProcessor sqlProcessor, WebDataTransferParameters parameters, DBSDataContainer dataContainer, @Nullable WebSQLResultsInfo resultsInfo) { sqlProcessor.getWebSession().addInfoMessage("Export data"); @@ -213,10 +218,18 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { StreamConsumerSettings settings = new StreamConsumerSettings(); - settings.setOutputEncodingBOM(false); settings.setOutputFolder(exportFile.getParent().toAbsolutePath().toString()); settings.setOutputFilePattern(exportFile.getFileName().toString()); + WebDataTransferOutputSettings outputSettings = parameters.getOutputSettings(); + settings.setOutputEncodingBOM(outputSettings.isInsertBom()); + if (!CommonUtils.isEmpty(outputSettings.getEncoding())) { + settings.setOutputEncoding(outputSettings.getEncoding()); + } + if (!CommonUtils.isEmpty(outputSettings.getTimestampPattern())) { + settings.setOutputTimestampPattern(outputSettings.getTimestampPattern()); + } + Map properties = new HashMap<>(); Map processorProperties = parameters.getProcessorProperties(); @@ -241,7 +254,7 @@ public class WebServiceDataTransfer implements DBWServiceDataTransfer { DatabaseProducerSettings producerSettings = new DatabaseProducerSettings(); producerSettings.setExtractType(DatabaseProducerSettings.ExtractType.SINGLE_QUERY); producerSettings.setQueryRowCount(false); - producerSettings.setOpenNewConnections(CommonUtils.getOption(parameters.getSettings(), "openNewConnection")); + producerSettings.setOpenNewConnections(CommonUtils.getOption(parameters.getDbProducerSettings(), "openNewConnection")); producer.transferData(monitor, consumer, null, producerSettings, null); diff --git a/webapp/packages/core-sdk/src/queries/data-transfer/getDataTransferDefaultParameters.gql b/webapp/packages/core-sdk/src/queries/data-transfer/getDataTransferDefaultParameters.gql new file mode 100644 index 0000000000..6a94c6c834 --- /dev/null +++ b/webapp/packages/core-sdk/src/queries/data-transfer/getDataTransferDefaultParameters.gql @@ -0,0 +1,10 @@ +query getDataTransferDefaultParameters { + settings: dataTransferDefaultExportSettings { + outputSettings { + insertBom + encoding + timestampPattern + } + supportedEncodings + } +} diff --git a/webapp/packages/core-sdk/src/sdk.ts b/webapp/packages/core-sdk/src/sdk.ts index 8d4723af70..b2449b6697 100644 --- a/webapp/packages/core-sdk/src/sdk.ts +++ b/webapp/packages/core-sdk/src/sdk.ts @@ -222,8 +222,26 @@ export interface ConnectionInfo { useUrl: Scalars['Boolean']; } +export interface DataTransferDefaultExportSettings { + outputSettings: DataTransferOutputSettings; + supportedEncodings: Array; +} + +export interface DataTransferOutputSettings { + encoding: Scalars['String']; + insertBom: Scalars['Boolean']; + timestampPattern: Scalars['String']; +} + +export interface DataTransferOutputSettingsInput { + encoding?: InputMaybe; + insertBom?: InputMaybe; + timestampPattern?: InputMaybe; +} + export interface DataTransferParameters { filter?: InputMaybe; + outputSettings?: InputMaybe; processorId: Scalars['ID']; processorProperties: Scalars['Object']; settings?: InputMaybe; @@ -831,6 +849,7 @@ export interface Query { createRole: AdminRoleInfo; createUser: AdminUserInfo; dataTransferAvailableStreamProcessors: Array; + dataTransferDefaultExportSettings: DataTransferDefaultExportSettings; dataTransferExportDataFromContainer: AsyncTaskInfo; dataTransferExportDataFromResults: AsyncTaskInfo; dataTransferRemoveDataFile?: Maybe; @@ -2143,6 +2162,11 @@ export type ExportDataFromResultsQueryVariables = Exact<{ export type ExportDataFromResultsQuery = { taskInfo: { id: string, name?: string, running: boolean, status?: string, taskResult?: any, error?: { message?: string, errorCode?: string, errorType?: string, stackTrace?: string } } }; +export type GetDataTransferDefaultParametersQueryVariables = Exact<{ [key: string]: never; }>; + + +export type GetDataTransferDefaultParametersQuery = { settings: { supportedEncodings: Array, outputSettings: { insertBom: boolean, encoding: string, timestampPattern: string } } }; + export type GetDataTransferProcessorsQueryVariables = Exact<{ [key: string]: never; }>; @@ -3553,6 +3577,18 @@ export const ExportDataFromResultsDocument = ` } } ${AsyncTaskInfoFragmentDoc}`; +export const GetDataTransferDefaultParametersDocument = ` + query getDataTransferDefaultParameters { + settings: dataTransferDefaultExportSettings { + outputSettings { + insertBom + encoding + timestampPattern + } + supportedEncodings + } +} + `; export const GetDataTransferProcessorsDocument = ` query getDataTransferProcessors { processors: dataTransferAvailableStreamProcessors { @@ -4403,6 +4439,9 @@ export function getSdk(client: GraphQLClient, withWrapper: SdkFunctionWrapper = exportDataFromResults(variables: ExportDataFromResultsQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { return withWrapper((wrappedRequestHeaders) => client.request(ExportDataFromResultsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'exportDataFromResults', 'query'); }, + getDataTransferDefaultParameters(variables?: GetDataTransferDefaultParametersQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { + return withWrapper((wrappedRequestHeaders) => client.request(GetDataTransferDefaultParametersDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getDataTransferDefaultParameters', 'query'); + }, getDataTransferProcessors(variables?: GetDataTransferProcessorsQueryVariables, requestHeaders?: Dom.RequestInit["headers"]): Promise { return withWrapper((wrappedRequestHeaders) => client.request(GetDataTransferProcessorsDocument, variables, {...requestHeaders, ...wrappedRequestHeaders}), 'getDataTransferProcessors', 'query'); }, diff --git a/webapp/packages/plugin-data-export/src/Dialog/DataExportController.ts b/webapp/packages/plugin-data-export/src/Dialog/DataExportController.ts index 620cb11eab..294eb558e0 100644 --- a/webapp/packages/plugin-data-export/src/Dialog/DataExportController.ts +++ b/webapp/packages/plugin-data-export/src/Dialog/DataExportController.ts @@ -13,10 +13,11 @@ import { injectable, IInitializableController, IDestructibleController } from '@ import { CommonDialogService } from '@cloudbeaver/core-dialogs'; import { NotificationService } from '@cloudbeaver/core-events'; import { ErrorDetailsDialog } from '@cloudbeaver/core-notifications'; -import { DataTransferProcessorInfo, GQLErrorCatcher } from '@cloudbeaver/core-sdk'; +import { DataTransferOutputSettings, DataTransferProcessorInfo, GQLErrorCatcher, ObjectPropertyInfo, ObjectPropertyLength } from '@cloudbeaver/core-sdk'; import { DataExportService } from '../DataExportService'; import type { IExportContext } from '../IExportContext'; +import { DefaultExportOutputSettingsResource } from './DefaultExportOutputSettingsResource'; export enum DataExportStep { DataTransferProcessor, @@ -44,6 +45,8 @@ export class DataExportController implements IInitializableController, IDestruct processorProperties: any = {}; properties: IProperty[] = []; + outputSettings: Partial = {}; + readonly error = new GQLErrorCatcher(); private context!: IExportContext; @@ -53,7 +56,8 @@ export class DataExportController implements IInitializableController, IDestruct constructor( private readonly dataExportService: DataExportService, private readonly notificationService: NotificationService, - private readonly commonDialogService: CommonDialogService + private readonly commonDialogService: CommonDialogService, + private readonly defaultExportOutputSettingsResource: DefaultExportOutputSettingsResource, ) { makeObservable(this, { step: observable, @@ -62,6 +66,7 @@ export class DataExportController implements IInitializableController, IDestruct processors: computed, processorProperties: observable, properties: observable, + outputSettings: observable, }); } @@ -69,6 +74,7 @@ export class DataExportController implements IInitializableController, IDestruct this.context = context; this.close = close; this.loadProcessors(); + this.loadDefaultOutputSettings(); } destruct(): void { @@ -88,6 +94,7 @@ export class DataExportController implements IInitializableController, IDestruct processorId: this.processor.id, processorProperties: this.processorProperties, filter: this.context.filter, + outputSettings: this.outputSettings, } ); this.close(); @@ -140,6 +147,17 @@ export class DataExportController implements IInitializableController, IDestruct this.notificationService.logException(exception, 'Can\'t load data export processors'); } } + + private async loadDefaultOutputSettings() { + try { + const data = await this.defaultExportOutputSettingsResource.load(); + if (data) { + Object.assign(this.outputSettings, data.outputSettings); + } + } catch (exception: any) { + this.notificationService.logException(exception, 'Can\'t load output settings'); + } + } } function sortProcessors(processorA: DataTransferProcessorInfo, processorB: DataTransferProcessorInfo): number { diff --git a/webapp/packages/plugin-data-export/src/Dialog/DataExportDialog.tsx b/webapp/packages/plugin-data-export/src/Dialog/DataExportDialog.tsx index 46aef14ae9..3bf7608071 100644 --- a/webapp/packages/plugin-data-export/src/Dialog/DataExportDialog.tsx +++ b/webapp/packages/plugin-data-export/src/Dialog/DataExportDialog.tsx @@ -30,6 +30,7 @@ export const DataExportDialog: DialogComponent = observer(functi processorProperties={controller.processorProperties} error={controller.error} isExporting={controller.isExporting} + outputSettings={controller.outputSettings} onShowDetails={controller.showDetails} onBack={() => controller.setStep(DataExportStep.DataTransferProcessor)} onClose={rejectDialog} diff --git a/webapp/packages/plugin-data-export/src/Dialog/DefaultExportOutputSettingsResource.ts b/webapp/packages/plugin-data-export/src/Dialog/DefaultExportOutputSettingsResource.ts new file mode 100644 index 0000000000..cbf233cfd4 --- /dev/null +++ b/webapp/packages/plugin-data-export/src/Dialog/DefaultExportOutputSettingsResource.ts @@ -0,0 +1,27 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2022 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 { injectable } from '@cloudbeaver/core-di'; +import { + GraphQLService, + CachedDataResource, + DataTransferDefaultExportSettings +} from '@cloudbeaver/core-sdk'; + +@injectable() +export class DefaultExportOutputSettingsResource + extends CachedDataResource { + + constructor(private readonly graphQLService: GraphQLService) { + super(null); + } + + async loader() { + return (await this.graphQLService.sdk.getDataTransferDefaultParameters()).settings; + } +} diff --git a/webapp/packages/plugin-data-export/src/Dialog/OutputOptionsForm.tsx b/webapp/packages/plugin-data-export/src/Dialog/OutputOptionsForm.tsx new file mode 100644 index 0000000000..078cbd50b8 --- /dev/null +++ b/webapp/packages/plugin-data-export/src/Dialog/OutputOptionsForm.tsx @@ -0,0 +1,70 @@ +/* + * CloudBeaver - Cloud Database Manager + * Copyright (C) 2020-2022 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 styled, { css } from 'reshadow'; + +import { Combobox, FieldCheckbox, Loader, useDataResource } from '@cloudbeaver/core-blocks'; +import type { DataTransferOutputSettings } from '@cloudbeaver/core-sdk'; + +import { DefaultExportOutputSettingsResource } from './DefaultExportOutputSettingsResource'; + +const styles = css` + Combobox { + width: 140px; + } + + root { + padding: 24px; + display: flex; + align-items: end; + } + + FieldCheckbox { + margin-bottom: 6px; + margin-left: 24px + } +`; + +interface Props { + outputSettings: Partial; +} + +export const OutputOptionsForm = observer(function OutputOptionsForm(props: Props) { + const resource = useDataResource(OutputOptionsForm, DefaultExportOutputSettingsResource, undefined); + + return ( + + {() => { + const data = resource.data; + + if (!data) { + return null; + } + + return styled(styles)( + + + Encoding + + + Insert BOM + + + ); + }} + + ); +}); diff --git a/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx b/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx index 1c2629b1c1..0d0d28ae83 100644 --- a/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx +++ b/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialog.tsx @@ -5,16 +5,18 @@ * 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 { useState } from 'react'; import styled, { css } from 'reshadow'; import { IProperty, PropertiesTable, ErrorMessage } from '@cloudbeaver/core-blocks'; import { CommonDialogWrapper } from '@cloudbeaver/core-dialogs'; import { useTranslate } from '@cloudbeaver/core-localization'; -import type { DataTransferProcessorInfo, GQLErrorCatcher } from '@cloudbeaver/core-sdk'; +import type { DataTransferOutputSettings, DataTransferProcessorInfo, GQLErrorCatcher } from '@cloudbeaver/core-sdk'; import { useStyles } from '@cloudbeaver/core-theming'; +import { ITabData, Tab, TabList, TabsState, UNDERLINE_TAB_STYLES } from '@cloudbeaver/core-ui'; +import { OutputOptionsForm } from './OutputOptionsForm'; import { ProcessorConfigureDialogFooter } from './ProcessorConfigureDialogFooter'; const styles = css` @@ -24,6 +26,7 @@ const styles = css` PropertiesTable { flex: 1; overflow: hidden; + padding: 12px 0; } message { margin: auto; @@ -34,12 +37,21 @@ const styles = css` bottom: 0; padding: 8px 24px; } + + TabList { + margin: 0 10px; + } + + ObjectPropertyInfoForm { + margin: 12px 0; + } `; interface Props { processor: DataTransferProcessorInfo; properties: IProperty[]; processorProperties: any; + outputSettings: Partial; error: GQLErrorCatcher; isExporting: boolean; onShowDetails: () => void; @@ -48,10 +60,16 @@ interface Props { onExport: () => void; } +enum SETTINGS_TABS { + EXTRACTION = 'EXTRACTION', + OUTPUT = 'OUTPUT', +} + export const ProcessorConfigureDialog = observer(function ProcessorConfigureDialog({ processor, properties, processorProperties, + outputSettings, error, isExporting, onShowDetails, @@ -61,17 +79,36 @@ export const ProcessorConfigureDialog = observer(function ProcessorConfig }) { const translate = useTranslate(); const title = `${translate('data_transfer_dialog_configuration_title')} (${processor.name})`; + const [currentTabId, setCurrentTabId] = useState(SETTINGS_TABS.EXTRACTION); - return styled(useStyles(styles))( + function handleTabChange(tab: ITabData) { + setCurrentTabId(tab.tabId as SETTINGS_TABS); + } + + function handleNextClick() { + setCurrentTabId(SETTINGS_TABS.OUTPUT); + } + + function handleBackClick() { + if (currentTabId === SETTINGS_TABS.OUTPUT) { + setCurrentTabId(SETTINGS_TABS.EXTRACTION); + } else { + onBack(); + } + } + + return styled(useStyles(UNDERLINE_TAB_STYLES, styles))( )} fixedSize @@ -79,10 +116,27 @@ export const ProcessorConfigureDialog = observer(function ProcessorConfig noBodyPadding onReject={onClose} > - + {!processor.isBinary ? ( + + + + {translate('data_transfer_format_settings')} + + + {translate('data_transfer_output_settings')} + + + + ) : null} + {currentTabId === SETTINGS_TABS.EXTRACTION ? ( + + ) : ( + + )} + {error.responseMessage && ( (function ProcessorConfig )} ); -} -); +}); diff --git a/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialogFooter.tsx b/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialogFooter.tsx index a2436cbfff..1914128b99 100644 --- a/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialogFooter.tsx +++ b/webapp/packages/plugin-data-export/src/Dialog/ProcessorConfigureDialogFooter.tsx @@ -32,16 +32,20 @@ const styles = css` interface Props { isExporting: boolean; + isFinalStep: boolean; onCancel: () => void; onExport: () => void; onBack: () => void; + onNext: () => void; } export const ProcessorConfigureDialogFooter = observer(function ProcessorConfigureDialogFooter({ isExporting, + isFinalStep, onCancel, onExport, onBack, + onNext, }) { const translate = useTranslate(); @@ -64,14 +68,25 @@ export const ProcessorConfigureDialogFooter = observer(function Processor > {translate('ui_processing_cancel')} - + {isFinalStep ? ( + + ) : ( + + )} ); } diff --git a/webapp/packages/plugin-data-export/src/locales/en.ts b/webapp/packages/plugin-data-export/src/locales/en.ts index 9566e31bb5..533819e1c7 100644 --- a/webapp/packages/plugin-data-export/src/locales/en.ts +++ b/webapp/packages/plugin-data-export/src/locales/en.ts @@ -12,4 +12,6 @@ export default [ ['data_transfer_notification_delete', 'Delete'], ['data_transfer_exporting_table', 'Table:'], ['data_transfer_exporting_sql', 'SQL:'], + ['data_transfer_format_settings', 'Format'], + ['data_transfer_output_settings', 'Output'], ]; diff --git a/webapp/packages/plugin-data-export/src/manifest.ts b/webapp/packages/plugin-data-export/src/manifest.ts index b874cda3be..7ab70a75d7 100644 --- a/webapp/packages/plugin-data-export/src/manifest.ts +++ b/webapp/packages/plugin-data-export/src/manifest.ts @@ -14,6 +14,7 @@ import { DataExportProcessService } from './DataExportProcessService'; import { DataExportService } from './DataExportService'; import { DataExportSettingsService } from './DataExportSettingsService'; import { DataTransferProcessorsResource } from './DataTransferProcessorsResource'; +import { DefaultExportOutputSettingsResource } from './Dialog/DefaultExportOutputSettingsResource'; import { LocaleService } from './LocaleService'; export const manifest: PluginManifest = { @@ -29,5 +30,6 @@ export const manifest: PluginManifest = { DataExportProcessService, DataTransferProcessorsResource, LocaleService, + DefaultExportOutputSettingsResource, ], };