From 2c259746f38136090a0d847225595cadedf67250 Mon Sep 17 00:00:00 2001 From: Alexey Antonov Date: Thu, 15 Sep 2022 23:33:11 +0300 Subject: [PATCH] add renewIDs method --- .../__snapshots__/utils.test.tsx.snap | 82 +++++++++++++++++++ .../indexpattern_datasource/indexpattern.tsx | 9 +- .../indexpattern_datasource/utils.test.tsx | 52 +++++++++++- .../public/indexpattern_datasource/utils.tsx | 14 ++++ x-pack/plugins/lens/public/utils.ts | 43 +++++++++- 5 files changed, 191 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/utils.test.tsx.snap diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/utils.test.tsx.snap b/x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/utils.test.tsx.snap new file mode 100644 index 0000000000000..93083a8ed3e88 --- /dev/null +++ b/x-pack/plugins/lens/public/indexpattern_datasource/__snapshots__/utils.test.tsx.snap @@ -0,0 +1,82 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`indexpattern_datasource utils cloneLayer should replace ids 1`] = ` +Object { + "a": Object { + "columnOrder": Array [ + "899ee4b6-3147-4d45-94bf-ea9c02e55d28", + "ae62cfc8-faa5-4096-a30c-f92ac59922a0", + ], + "columns": Object { + "899ee4b6-3147-4d45-94bf-ea9c02e55d28": Object { + "params": Object { + "orderBy": Object { + "columnId": "ae62cfc8-faa5-4096-a30c-f92ac59922a0", + "type": "column", + }, + "orderDirection": "desc", + }, + }, + "ae62cfc8-faa5-4096-a30c-f92ac59922a0": Object { + "params": Object { + "emptyAsNull": true, + "justForTest": Array [ + "899ee4b6-3147-4d45-94bf-ea9c02e55d28", + "ae62cfc8-faa5-4096-a30c-f92ac59922a0", + ], + "justForTest2": Array [ + Object { + "899ee4b6-3147-4d45-94bf-ea9c02e55d28": Array [ + Object { + "c": "ae62cfc8-faa5-4096-a30c-f92ac59922a0", + }, + ], + "a": "899ee4b6-3147-4d45-94bf-ea9c02e55d28", + }, + ], + }, + }, + }, + "incompleteColumns": Object {}, + "indexPatternId": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + }, + "b": Object { + "columnOrder": Array [ + "899ee4b6-3147-4d45-94bf-ea9c02e55d28C", + "ae62cfc8-faa5-4096-a30c-f92ac59922a0C", + ], + "columns": Object { + "899ee4b6-3147-4d45-94bf-ea9c02e55d28C": Object { + "params": Object { + "orderBy": Object { + "columnId": "ae62cfc8-faa5-4096-a30c-f92ac59922a0C", + "type": "column", + }, + "orderDirection": "desc", + }, + }, + "ae62cfc8-faa5-4096-a30c-f92ac59922a0C": Object { + "params": Object { + "emptyAsNull": true, + "justForTest": Array [ + "899ee4b6-3147-4d45-94bf-ea9c02e55d28C", + "ae62cfc8-faa5-4096-a30c-f92ac59922a0C", + ], + "justForTest2": Array [ + Object { + "899ee4b6-3147-4d45-94bf-ea9c02e55d28C": Array [ + Object { + "c": "ae62cfc8-faa5-4096-a30c-f92ac59922a0C", + }, + ], + "a": "899ee4b6-3147-4d45-94bf-ea9c02e55d28C", + }, + ], + }, + }, + }, + "incompleteColumns": Object {}, + "indexPatternId": "ff959d40-b880-11e8-a6d9-e546fe2bba5f", + }, +} +`; diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx index d64b273b2b480..8de8527f2aae9 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.tsx @@ -66,6 +66,7 @@ import { getTSDBRollupWarningMessages, getVisualDefaultsForLayer, isColumnInvalid, + cloneLayer, } from './utils'; import { normalizeOperationDataType, isDraggedField } from './pure_utils'; import { LayerPanel } from './layerpanel'; @@ -190,15 +191,9 @@ export function getIndexPatternDatasource({ }, cloneLayer(state: IndexPatternPrivateState, layerId: string, newLayerId: string) { - // @todo: wip return { ...state, - layers: { - ...state.layers, - [newLayerId]: { - ...state.layers[layerId], - }, - }, + layers: cloneLayer(state.layers, layerId, newLayerId), }; }, diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx index 3bfcd51fb3907..76b73433018bf 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/utils.test.tsx @@ -8,7 +8,7 @@ import React from 'react'; import { shallow } from 'enzyme'; import { createDatatableUtilitiesMock } from '@kbn/data-plugin/common/mocks'; -import { getPrecisionErrorWarningMessages } from './utils'; +import { getPrecisionErrorWarningMessages, cloneLayer } from './utils'; import type { IndexPatternPrivateState, GenericIndexPatternColumn } from './types'; import type { FramePublicAPI } from '../types'; import type { DocLinksStart } from '@kbn/core/public'; @@ -16,6 +16,7 @@ import { EuiButton } from '@elastic/eui'; import { TermsIndexPatternColumn } from './operations'; import { mountWithIntl } from '@kbn/test-jest-helpers'; import { FormattedMessage } from '@kbn/i18n-react'; +import { IndexPatternLayer } from './types'; describe('indexpattern_datasource utils', () => { describe('getPrecisionErrorWarningMessages', () => { @@ -196,4 +197,53 @@ describe('indexpattern_datasource utils', () => { }); }); }); + + describe('cloneLayer', () => { + test('should replace ids', () => { + expect( + cloneLayer( + { + a: { + columns: { + '899ee4b6-3147-4d45-94bf-ea9c02e55d28': { + params: { + orderBy: { + type: 'column', + columnId: 'ae62cfc8-faa5-4096-a30c-f92ac59922a0', + }, + orderDirection: 'desc', + }, + }, + 'ae62cfc8-faa5-4096-a30c-f92ac59922a0': { + params: { + emptyAsNull: true, + justForTest: [ + '899ee4b6-3147-4d45-94bf-ea9c02e55d28', + 'ae62cfc8-faa5-4096-a30c-f92ac59922a0', + ], + justForTest2: [ + { + a: '899ee4b6-3147-4d45-94bf-ea9c02e55d28', + ['899ee4b6-3147-4d45-94bf-ea9c02e55d28']: [ + { c: 'ae62cfc8-faa5-4096-a30c-f92ac59922a0' }, + ], + }, + ], + }, + }, + }, + columnOrder: [ + '899ee4b6-3147-4d45-94bf-ea9c02e55d28', + 'ae62cfc8-faa5-4096-a30c-f92ac59922a0', + ], + incompleteColumns: {}, + indexPatternId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + }, + } as unknown as Record, + 'a', + 'b' + ) + ).toMatchSnapshot(); + }); + }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx index f2ad60193ca3d..21ba6746a810e 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx +++ b/x-pack/plugins/lens/public/indexpattern_datasource/utils.tsx @@ -18,6 +18,7 @@ import { groupBy, escape, uniq } from 'lodash'; import type { Query } from '@kbn/data-plugin/common'; import { SearchResponseWarning } from '@kbn/data-plugin/public/search/types'; import type { FramePublicAPI, IndexPattern, StateSetter } from '../types'; +import { renewIDs } from '../utils'; import type { IndexPatternLayer, IndexPatternPersistedState, @@ -622,3 +623,16 @@ export function getFiltersInLayer( }, }; } + +export const cloneLayer = ( + layers: Record, + layerId: string, + newLayerId: string +): Record => ({ + ...layers, + [newLayerId]: renewIDs( + Object.keys(layers[layerId]?.columns ?? {}), + layers[layerId], + (k: string) => k + 'C' + ), +}); diff --git a/x-pack/plugins/lens/public/utils.ts b/x-pack/plugins/lens/public/utils.ts index 385a533dc7c75..5c15251a01d89 100644 --- a/x-pack/plugins/lens/public/utils.ts +++ b/x-pack/plugins/lens/public/utils.ts @@ -4,9 +4,10 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ -import { uniq } from 'lodash'; +import { set, uniq, cloneDeep } from 'lodash'; import { i18n } from '@kbn/i18n'; import moment from 'moment-timezone'; +import type { Serializable } from '@kbn/utility-types'; import type { TimefilterContract } from '@kbn/data-plugin/public'; import type { IUiSettingsClient, SavedObjectReference } from '@kbn/core/public'; @@ -195,6 +196,46 @@ export function inferTimeField( .find(Boolean); } +export function renewIDs( + forRenewIds: string[], + obj: T, + getNewId: (id: string) => string +): T { + obj = cloneDeep(obj); + const recursiveFn = ( + item: Serializable, + parent?: Record | Serializable[], + key?: string | number + ) => { + if (typeof item === 'object') { + if (Array.isArray(item)) { + item.forEach((a, k, ref) => recursiveFn(a, ref, k)); + } else { + if (item) { + Object.keys(item).forEach((k) => { + let newId = k; + if (forRenewIds.includes(k)) { + newId = getNewId(k); + item[newId] = item[k]; + delete item[k]; + } + recursiveFn(item[newId], item, newId); + }); + } + } + } else if ( + parent && + key !== undefined && + typeof item === 'string' && + forRenewIds.includes(item) + ) { + set(parent, key, getNewId(item)); + } + }; + recursiveFn(obj as unknown as Serializable); + return obj; +} + /** * The dimension container is set up to close when it detects a click outside it. * Use this CSS class to exclude particular elements from this behavior.