diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.exporters.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.exporters.md index 883dbcfe289cb2..efba24c008264d 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.exporters.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.exporters.md @@ -10,5 +10,7 @@ exporters: { datatableToCSV: typeof datatableToCSV; CSV_MIME_TYPE: string; + cellHasFormulas: (val: string) => boolean; + tableHasFormulas: (columns: import("../../expressions").DatatableColumn[], rows: Record[]) => boolean; } ``` diff --git a/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx b/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx index 20144b47e474bd..2d12d6e7975284 100644 --- a/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx +++ b/src/plugins/dashboard/public/application/actions/export_csv_action.test.tsx @@ -105,7 +105,7 @@ describe('Export CSV action', () => { | Record; expect(result).toEqual({ 'Hello Kibana.csv': { - content: `First Name,Last Name${LINE_FEED_CHARACTER}Kibana,undefined${LINE_FEED_CHARACTER}`, + content: `First Name,Last Name${LINE_FEED_CHARACTER}Kibana,${LINE_FEED_CHARACTER}`, type: 'text/plain;charset=utf-8', }, }); diff --git a/src/plugins/dashboard/public/application/actions/export_csv_action.tsx b/src/plugins/dashboard/public/application/actions/export_csv_action.tsx index c2f651360da1bd..dd6eeb92ef932d 100644 --- a/src/plugins/dashboard/public/application/actions/export_csv_action.tsx +++ b/src/plugins/dashboard/public/application/actions/export_csv_action.tsx @@ -94,6 +94,7 @@ export class ExportCSVAction implements Action { csvSeparator: this.params.core.uiSettings.get('csv:separator', ','), quoteValues: this.params.core.uiSettings.get('csv:quoteValues', true), formatFactory, + escapeFormulaValues: false, }), type: exporters.CSV_MIME_TYPE, }; diff --git a/src/plugins/data/common/exports/constants.ts b/src/plugins/data/common/exports/constants.ts new file mode 100644 index 00000000000000..9c256d4d3ea97e --- /dev/null +++ b/src/plugins/data/common/exports/constants.ts @@ -0,0 +1,11 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +export const CSV_FORMULA_CHARS = ['=', '+', '-', '@']; +export const nonAlphaNumRE = /[^a-zA-Z0-9]/; +export const allDoubleQuoteRE = /"/g; diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/escape_value.test.ts b/src/plugins/data/common/exports/escape_value.test.ts similarity index 93% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/escape_value.test.ts rename to src/plugins/data/common/exports/escape_value.test.ts index 6bc1a3b4627a68..9463af644d4179 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/escape_value.test.ts +++ b/src/plugins/data/common/exports/escape_value.test.ts @@ -1,8 +1,9 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ import expect from '@kbn/expect'; diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/escape_value.ts b/src/plugins/data/common/exports/escape_value.ts similarity index 65% rename from x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/escape_value.ts rename to src/plugins/data/common/exports/escape_value.ts index e4dbdb2f396a46..9277f792a4b864 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/escape_value.ts +++ b/src/plugins/data/common/exports/escape_value.ts @@ -1,15 +1,14 @@ /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. */ +import { allDoubleQuoteRE, nonAlphaNumRE } from './constants'; +import { cellHasFormulas } from './formula_checks'; -import { RawValue } from '../types'; -import { cellHasFormulas } from './cell_has_formula'; - -const nonAlphaNumRE = /[^a-zA-Z0-9]/; -const allDoubleQuoteRE = /"/g; +type RawValue = string | object | null | undefined; export function createEscapeValue( quoteValues: boolean, @@ -22,7 +21,6 @@ export function createEscapeValue( return `"${formulasEscaped.replace(allDoubleQuoteRE, '""')}"`; } } - return val == null ? '' : val.toString(); }; } diff --git a/src/plugins/data/common/exports/export_csv.test.ts b/src/plugins/data/common/exports/export_csv.test.ts index 2070ec9417cd16..8bf44fe48a5890 100644 --- a/src/plugins/data/common/exports/export_csv.test.ts +++ b/src/plugins/data/common/exports/export_csv.test.ts @@ -17,6 +17,7 @@ function getDefaultOptions() { csvSeparator: ',', quoteValues: true, formatFactory, + escapeFormulaValues: false, }; } @@ -71,4 +72,16 @@ describe('CSV exporter', () => { 'columnOne\r\n"Formatted_""value"""\r\n' ); }); + + test('should escape formulas', () => { + const datatable = getDataTable(); + datatable.rows[0].col1 = '=1'; + expect( + datatableToCSV(datatable, { + ...getDefaultOptions(), + escapeFormulaValues: true, + formatFactory: () => ({ convert: (v: unknown) => v } as FieldFormat), + }) + ).toMatch('columnOne\r\n"\'=1"\r\n'); + }); }); diff --git a/src/plugins/data/common/exports/export_csv.tsx b/src/plugins/data/common/exports/export_csv.tsx index f52e227c667cc7..d4477e72b64c41 100644 --- a/src/plugins/data/common/exports/export_csv.tsx +++ b/src/plugins/data/common/exports/export_csv.tsx @@ -10,40 +10,26 @@ import { FormatFactory } from 'src/plugins/data/common/field_formats/utils'; import { Datatable } from 'src/plugins/expressions'; +import { createEscapeValue } from './escape_value'; export const LINE_FEED_CHARACTER = '\r\n'; -const nonAlphaNumRE = /[^a-zA-Z0-9]/; -const allDoubleQuoteRE = /"/g; export const CSV_MIME_TYPE = 'text/plain;charset=utf-8'; -// TODO: enhance this later on -function escape(val: object | string, quoteValues: boolean) { - if (val != null && typeof val === 'object') { - val = val.valueOf(); - } - - val = String(val); - - if (quoteValues && nonAlphaNumRE.test(val)) { - val = `"${val.replace(allDoubleQuoteRE, '""')}"`; - } - - return val; -} - interface CSVOptions { csvSeparator: string; quoteValues: boolean; + escapeFormulaValues: boolean; formatFactory: FormatFactory; raw?: boolean; } export function datatableToCSV( { columns, rows }: Datatable, - { csvSeparator, quoteValues, formatFactory, raw }: CSVOptions + { csvSeparator, quoteValues, formatFactory, raw, escapeFormulaValues }: CSVOptions ) { + const escapeValues = createEscapeValue(quoteValues, escapeFormulaValues); // Build the header row by its names - const header = columns.map((col) => escape(col.name, quoteValues)); + const header = columns.map((col) => escapeValues(col.name)); const formatters = columns.reduce>>( (memo, { id, meta }) => { @@ -56,7 +42,7 @@ export function datatableToCSV( // Convert the array of row objects to an array of row arrays const csvRows = rows.map((row) => { return columns.map((column) => - escape(raw ? row[column.id] : formatters[column.id].convert(row[column.id]), quoteValues) + escapeValues(raw ? row[column.id] : formatters[column.id].convert(row[column.id])) ); }); diff --git a/src/plugins/data/common/exports/formula_checks.ts b/src/plugins/data/common/exports/formula_checks.ts new file mode 100644 index 00000000000000..eed339c15781c9 --- /dev/null +++ b/src/plugins/data/common/exports/formula_checks.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0 and the Server Side Public License, v 1; you may not use this file except + * in compliance with, at your election, the Elastic License 2.0 or the Server + * Side Public License, v 1. + */ + +import { startsWith } from 'lodash'; +import { Datatable } from 'src/plugins/expressions'; +import { CSV_FORMULA_CHARS } from './constants'; + +export const cellHasFormulas = (val: string) => + CSV_FORMULA_CHARS.some((formulaChar) => startsWith(val, formulaChar)); + +export const tableHasFormulas = (columns: Datatable['columns'], rows: Datatable['rows']) => { + return ( + columns.some(({ name }) => cellHasFormulas(name)) || + rows.some((row) => columns.some(({ id }) => cellHasFormulas(row[id]))) + ); +}; diff --git a/src/plugins/data/common/exports/index.ts b/src/plugins/data/common/exports/index.ts index 9e6fb10fae84c4..1dbc4a17091bc5 100644 --- a/src/plugins/data/common/exports/index.ts +++ b/src/plugins/data/common/exports/index.ts @@ -7,3 +7,6 @@ */ export { datatableToCSV, CSV_MIME_TYPE } from './export_csv'; +export { createEscapeValue } from './escape_value'; +export { CSV_FORMULA_CHARS } from './constants'; +export { cellHasFormulas, tableHasFormulas } from './formula_checks'; diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 9af1cbf95d94da..51f3d9fd660e51 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -209,10 +209,12 @@ export { * Exporters (CSV) */ -import { datatableToCSV, CSV_MIME_TYPE } from '../common'; +import { datatableToCSV, CSV_MIME_TYPE, cellHasFormulas, tableHasFormulas } from '../common'; export const exporters = { datatableToCSV, CSV_MIME_TYPE, + cellHasFormulas, + tableHasFormulas, }; /* diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 4508ad5948927f..276320eb1a6ab7 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -927,6 +927,8 @@ export type ExistsFilter = Filter & { export const exporters: { datatableToCSV: typeof datatableToCSV; CSV_MIME_TYPE: string; + cellHasFormulas: (val: string) => boolean; + tableHasFormulas: (columns: import("../../expressions").DatatableColumn[], rows: Record[]) => boolean; }; // Warning: (ae-missing-release-tag) "ExpressionFunctionKibana" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -2777,25 +2779,25 @@ export interface WaitUntilNextSessionCompletesOptions { // src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "TruncateFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:170:26 - (ae-forgotten-export) The symbol "HistogramFormat" needs to be exported by the entry point index.d.ts // src/plugins/data/public/index.ts:213:23 - (ae-forgotten-export) The symbol "datatableToCSV" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:410:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:410:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:410:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "IpAddress" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:425:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:429:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:430:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:433:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:434:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts -// src/plugins/data/public/index.ts:437:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:240:27 - (ae-forgotten-export) The symbol "isFilterable" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:240:27 - (ae-forgotten-export) The symbol "isNestedField" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:240:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:240:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:240:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:412:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:412:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:412:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:414:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:425:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:426:1 - (ae-forgotten-export) The symbol "IpAddress" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:431:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:432:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:435:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:436:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts +// src/plugins/data/public/index.ts:439:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts // src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts // src/plugins/data/public/search/session/session_service.ts:62:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts diff --git a/src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx b/src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx index 4b5a80e9b07439..e6b40bcb5936c4 100644 --- a/src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx +++ b/src/plugins/data/public/utils/table_inspector_view/components/data_view.test.tsx @@ -16,6 +16,7 @@ jest.mock('../../../../../share/public', () => ({ })); jest.mock('../../../../common', () => ({ datatableToCSV: jest.fn().mockReturnValue('csv'), + tableHasFormulas: jest.fn().mockReturnValue(false), })); describe('Inspector Data View', () => { diff --git a/src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx b/src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx index 07230a29ca3f5a..e79a1c2b52e03d 100644 --- a/src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx +++ b/src/plugins/data/public/utils/table_inspector_view/components/download_options.tsx @@ -7,12 +7,19 @@ */ import React, { Component } from 'react'; +import { memoize } from 'lodash'; import PropTypes from 'prop-types'; import { FormattedMessage } from '@kbn/i18n/react'; import { i18n } from '@kbn/i18n'; -import { EuiButton, EuiContextMenuItem, EuiContextMenuPanel, EuiPopover } from '@elastic/eui'; -import { CSV_MIME_TYPE, datatableToCSV } from '../../../../common'; +import { + EuiButton, + EuiContextMenuItem, + EuiContextMenuPanel, + EuiPopover, + EuiToolTip, +} from '@elastic/eui'; +import { CSV_MIME_TYPE, datatableToCSV, tableHasFormulas } from '../../../../common'; import { Datatable } from '../../../../../expressions'; import { downloadMultipleAs } from '../../../../../share/public'; import { FieldFormatsStart } from '../../../field_formats'; @@ -30,6 +37,10 @@ interface DataDownloadOptionsProps { fieldFormats: FieldFormatsStart; } +const detectFormulasInTables = memoize((datatables: Datatable[]) => + datatables.some(({ columns, rows }) => tableHasFormulas(columns, rows)) +); + class DataDownloadOptions extends Component { static propTypes = { title: PropTypes.string.isRequired, @@ -74,6 +85,7 @@ class DataDownloadOptions extends Component ); + const downloadButton = detectedFormulasInTables ? ( + + {button} + + ) : ( + button + ); + const items = [ (); + const detectedFormulasInTable = exporters.tableHasFormulas(columns, rows); + const onClickExport = useCallback( (formatted: boolean) => { const csvSeparator = uiSettings.get(CSV_SEPARATOR_SETTING); @@ -55,6 +63,7 @@ export const TableVisControls = memo( quoteValues, formatFactory: getFormatService().deserialize, raw: !formatted, + escapeFormulaValues: false, } ); downloadFileAs(`${filename || 'unsaved'}.csv`, { content, type: exporters.CSV_MIME_TYPE }); @@ -85,6 +94,20 @@ export const TableVisControls = memo( ); + const downloadButton = detectedFormulasInTable ? ( + + {button} + + ) : ( + button + ); + const items = [ onClickExport(false)}> @@ -100,7 +123,7 @@ export const TableVisControls = memo( return ( { + if (activeData) { + const datatables = Object.values(activeData); + const formulaDetected = datatables.some((datatable) => { + return tableHasFormulas(datatable.columns, datatable.rows); + }); + if (formulaDetected) { + return i18n.translate('xpack.lens.app.downloadButtonFormulasWarning', { + defaultMessage: + 'Your CSV contains characters which spreadsheet applications can interpret as formulas', + }); + } + } + return undefined; + }, + }, actions: { exportToCSV: () => { if (!activeData) { @@ -230,6 +256,7 @@ export const LensTopNavMenu = ({ csvSeparator: uiSettings.get('csv:separator', ','), quoteValues: uiSettings.get('csv:quoteValues', true), formatFactory: data.fieldFormats.deserialize, + escapeFormulaValues: false, }), type: exporters.CSV_MIME_TYPE, }; diff --git a/x-pack/plugins/lens/public/app_plugin/types.ts b/x-pack/plugins/lens/public/app_plugin/types.ts index 7f1c21fa5a9bdf..499ba3c86bca57 100644 --- a/x-pack/plugins/lens/public/app_plugin/types.ts +++ b/x-pack/plugins/lens/public/app_plugin/types.ts @@ -114,6 +114,10 @@ export interface LensAppServices { dashboardFeatureFlag: DashboardFeatureFlagConfig; } +export interface LensTopNavTooltips { + showExportWarning: () => string | undefined; +} + export interface LensTopNavActions { saveAndReturn: () => void; showSaveModal: () => void; diff --git a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/check_cells_for_formulas.ts b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/check_cells_for_formulas.ts index f650bbaed12717..709c0ccd67e9ce 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/check_cells_for_formulas.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/check_cells_for_formulas.ts @@ -6,7 +6,7 @@ */ import { pick, keys, values, some } from 'lodash'; -import { cellHasFormulas } from '../../csv_searchsource/generate_csv/cell_has_formula'; +import { cellHasFormulas } from '../../../../../../../src/plugins/data/common'; interface IFlattened { [header: string]: string; diff --git a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts index e5ed04f4cab66e..c1018030827c06 100644 --- a/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts +++ b/x-pack/plugins/reporting/server/export_types/csv/generate_csv/index.ts @@ -8,12 +8,12 @@ import { i18n } from '@kbn/i18n'; import { ElasticsearchClient, IUiSettingsClient } from 'src/core/server'; import { ReportingConfig } from '../../../'; +import { createEscapeValue } from '../../../../../../../src/plugins/data/common'; import { CancellationToken } from '../../../../../../plugins/reporting/common'; import { CSV_BOM_CHARS } from '../../../../common/constants'; import { byteSizeValueToNumber } from '../../../../common/schema_utils'; import { LevelLogger } from '../../../lib'; import { getFieldFormats } from '../../../services'; -import { createEscapeValue } from '../../csv_searchsource/generate_csv/escape_value'; import { MaxSizeStringBuilder } from '../../csv_searchsource/generate_csv/max_size_string_builder'; import { IndexPatternSavedObjectDeprecatedCSV, diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/cell_has_formula.ts b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/cell_has_formula.ts deleted file mode 100644 index aa361fcfbc1950..00000000000000 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/cell_has_formula.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { startsWith } from 'lodash'; -import { CSV_FORMULA_CHARS } from '../../../../common/constants'; - -export const cellHasFormulas = (val: string) => - CSV_FORMULA_CHARS.some((formulaChar) => startsWith(val, formulaChar)); diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts index 1d70b656fed360..254bc0ae21f6ca 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts +++ b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/generate_csv.ts @@ -22,6 +22,7 @@ import { SearchFieldValue, SearchSourceFields, tabifyDocs, + cellHasFormulas, } from '../../../../../../../src/plugins/data/common'; import { KbnServerError } from '../../../../../../../src/plugins/kibana_utils/server'; import { CancellationToken } from '../../../../common'; @@ -30,7 +31,6 @@ import { byteSizeValueToNumber } from '../../../../common/schema_utils'; import { LevelLogger } from '../../../lib'; import { TaskRunResult } from '../../../lib/tasks'; import { JobParamsCSV } from '../types'; -import { cellHasFormulas } from './cell_has_formula'; import { CsvExportSettings, getExportSettings } from './get_export_settings'; import { MaxSizeStringBuilder } from './max_size_string_builder'; diff --git a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/get_export_settings.ts b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/get_export_settings.ts index 17a10f3034242d..0b8815836367f2 100644 --- a/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/get_export_settings.ts +++ b/x-pack/plugins/reporting/server/export_types/csv_searchsource/generate_csv/get_export_settings.ts @@ -8,6 +8,7 @@ import { ByteSizeValue } from '@kbn/config-schema'; import { i18n } from '@kbn/i18n'; import { IUiSettingsClient } from 'kibana/server'; +import { createEscapeValue } from '../../../../../../../src/plugins/data/common'; import { ReportingConfig } from '../../../'; import { CSV_BOM_CHARS, @@ -16,7 +17,6 @@ import { UI_SETTINGS_CSV_SEPARATOR, } from '../../../../common/constants'; import { LevelLogger } from '../../../lib'; -import { createEscapeValue } from './escape_value'; export interface CsvExportSettings { timezone: string;