-
Notifications
You must be signed in to change notification settings - Fork 8.3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove nested table splits from table vis (#26057)
- Loading branch information
1 parent
3038ea8
commit c6f0595
Showing
14 changed files
with
357 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
src/legacy/core_plugins/kibana/public/visualize/editor/lib/index.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you 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. | ||
*/ | ||
|
||
export { migrateAppState } from './migrate_app_state'; |
61 changes: 61 additions & 0 deletions
61
src/legacy/core_plugins/kibana/public/visualize/editor/lib/migrate_app_state.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you 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. | ||
*/ | ||
|
||
import { get, omit } from 'lodash'; | ||
|
||
/** | ||
* Creates a new instance of AppState based on the table vis state. | ||
* | ||
* Dashboards have a similar implementation; see | ||
* core_plugins/kibana/public/dashboard/lib/migrate_app_state | ||
* | ||
* @param appState {AppState} AppState class to instantiate | ||
*/ | ||
export function migrateAppState(appState) { | ||
// For BWC in pre 7.0 versions where table visualizations could have multiple aggs | ||
// with `schema === 'split'`. This ensures that bookmarked URLs with deprecated params | ||
// are rewritten to the correct state. See core_plugins/table_vis/migrations. | ||
if (appState.vis.type !== 'table') { | ||
return; | ||
} | ||
|
||
const visAggs = get(appState, 'vis.aggs', []); | ||
let splitCount = 0; | ||
const migratedAggs = visAggs.map(agg => { | ||
if (agg.schema !== 'split') { | ||
return agg; | ||
} | ||
|
||
splitCount++; | ||
if (splitCount === 1) { | ||
return agg; // leave the first split agg unchanged | ||
} | ||
agg.schema = 'bucket'; | ||
// the `row` param is exclusively used by split aggs, so we remove it | ||
agg.params = omit(agg.params, ['row']); | ||
return agg; | ||
}); | ||
|
||
if (splitCount <= 1) { | ||
return; // do nothing; we only want to touch tables with multiple split aggs | ||
} | ||
|
||
appState.vis.aggs = migratedAggs; | ||
appState.save(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you 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. | ||
*/ | ||
|
||
import { cloneDeep, get, omit } from 'lodash'; | ||
|
||
export const migrations = { | ||
visualization: { | ||
'7.0.0': (doc) => { | ||
try { | ||
const visState = JSON.parse(doc.attributes.visState); | ||
if (get(visState, 'type') !== 'table') { | ||
return doc; // do nothing; we only want to touch tables | ||
} | ||
|
||
let splitCount = 0; | ||
visState.aggs = visState.aggs.map(agg => { | ||
if (agg.schema !== 'split') { | ||
return agg; | ||
} | ||
|
||
splitCount++; | ||
if (splitCount === 1) { | ||
return agg; // leave the first split agg unchanged | ||
} | ||
agg.schema = 'bucket'; | ||
// the `row` param is exclusively used by split aggs, so we remove it | ||
agg.params = omit(agg.params, ['row']); | ||
return agg; | ||
}); | ||
|
||
if (splitCount <= 1) { | ||
return doc; // do nothing; we only want to touch tables with multiple split aggs | ||
} | ||
|
||
const newDoc = cloneDeep(doc); | ||
newDoc.attributes.visState = JSON.stringify(visState); | ||
return newDoc; | ||
} catch (e) { | ||
throw new Error(`Failure attempting to migrate saved object '${doc.attributes.title}' - ${e}`); | ||
} | ||
} | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
/* | ||
* Licensed to Elasticsearch B.V. under one or more contributor | ||
* license agreements. See the NOTICE file distributed with | ||
* this work for additional information regarding copyright | ||
* ownership. Elasticsearch B.V. licenses this file to you 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. | ||
*/ | ||
|
||
import { migrations } from './migrations'; | ||
|
||
describe('table vis migrations', () => { | ||
|
||
describe('7.0.0', () => { | ||
const migrate = doc => migrations.visualization['7.0.0'](doc); | ||
const generateDoc = ({ type, aggs }) => ({ | ||
attributes: { | ||
title: 'My Vis', | ||
description: 'This is my super cool vis.', | ||
visState: JSON.stringify({ type, aggs }), | ||
uiStateJSON: '{}', | ||
version: 1, | ||
kibanaSavedObjectMeta: { | ||
searchSourceJSON: '{}' | ||
} | ||
} | ||
}); | ||
|
||
it('should return a new object if vis is table and has multiple split aggs', () => { | ||
const aggs = [ | ||
{ | ||
id: '1', | ||
schema: 'metric', | ||
params: {} | ||
}, | ||
{ | ||
id: '2', | ||
schema: 'split', | ||
params: { foo: 'bar', row: true } | ||
}, | ||
{ | ||
id: '3', | ||
schema: 'split', | ||
params: { hey: 'ya', row: false } | ||
}, | ||
]; | ||
const tableDoc = generateDoc({ type: 'table', aggs }); | ||
const expected = tableDoc; | ||
const actual = migrate(tableDoc); | ||
expect(actual).not.toBe(expected); | ||
}); | ||
|
||
it('should not touch any vis that is not table', () => { | ||
const aggs = []; | ||
const pieDoc = generateDoc({ type: 'pie', aggs }); | ||
const expected = pieDoc; | ||
const actual = migrate(pieDoc); | ||
expect(actual).toBe(expected); | ||
}); | ||
|
||
it('should not change values in any vis that is not table', () => { | ||
const aggs = [ | ||
{ | ||
id: '1', | ||
schema: 'metric', | ||
params: {} | ||
}, | ||
{ | ||
id: '2', | ||
schema: 'split', | ||
params: { foo: 'bar', row: true } | ||
}, | ||
{ | ||
id: '3', | ||
schema: 'segment', | ||
params: { hey: 'ya' } | ||
} | ||
]; | ||
const pieDoc = generateDoc({ type: 'pie', aggs }); | ||
const expected = pieDoc; | ||
const actual = migrate(pieDoc); | ||
expect(actual).toEqual(expected); | ||
}); | ||
|
||
it('should not touch table vis if there are not multiple split aggs', () => { | ||
const aggs = [ | ||
{ | ||
id: '1', | ||
schema: 'metric', | ||
params: {} | ||
}, | ||
{ | ||
id: '2', | ||
schema: 'split', | ||
params: { foo: 'bar', row: true } | ||
} | ||
]; | ||
const tableDoc = generateDoc({ type: 'table', aggs }); | ||
const expected = tableDoc; | ||
const actual = migrate(tableDoc); | ||
expect(actual).toBe(expected); | ||
}); | ||
|
||
it('should change all split aggs to `bucket` except the first', () => { | ||
const aggs = [ | ||
{ | ||
id: '1', | ||
schema: 'metric', | ||
params: {} | ||
}, | ||
{ | ||
id: '2', | ||
schema: 'split', | ||
params: { foo: 'bar', row: true } | ||
}, | ||
{ | ||
id: '3', | ||
schema: 'split', | ||
params: { hey: 'ya', row: false } | ||
}, | ||
{ | ||
id: '4', | ||
schema: 'bucket', | ||
params: { heyyy: 'yaaa' } | ||
} | ||
]; | ||
const expected = ['metric', 'split', 'bucket', 'bucket']; | ||
const migrated = migrate(generateDoc({ type: 'table', aggs })); | ||
const actual = JSON.parse(migrated.attributes.visState); | ||
expect(actual.aggs.map(agg => agg.schema)).toEqual(expected); | ||
}); | ||
|
||
it('should remove `rows` param from any aggs that are not `split`', () => { | ||
const aggs = [ | ||
{ | ||
id: '1', | ||
schema: 'metric', | ||
params: {} | ||
}, | ||
{ | ||
id: '2', | ||
schema: 'split', | ||
params: { foo: 'bar', row: true } | ||
}, | ||
{ | ||
id: '3', | ||
schema: 'split', | ||
params: { hey: 'ya', row: false } | ||
} | ||
]; | ||
const expected = [{}, { foo: 'bar', row: true }, { hey: 'ya' }]; | ||
const migrated = migrate(generateDoc({ type: 'table', aggs })); | ||
const actual = JSON.parse(migrated.attributes.visState); | ||
expect(actual.aggs.map(agg => agg.params)).toEqual(expected); | ||
}); | ||
|
||
it('should throw with a reference to the doc name if something goes wrong', () => { | ||
const doc = { | ||
attributes: { | ||
title: 'My Vis', | ||
description: 'This is my super cool vis.', | ||
visState: '!/// Intentionally malformed JSON ///!', | ||
uiStateJSON: '{}', | ||
version: 1, | ||
kibanaSavedObjectMeta: { | ||
searchSourceJSON: '{}' | ||
} | ||
} | ||
}; | ||
expect(() => migrate(doc)).toThrowError(/My Vis/); | ||
}); | ||
}); | ||
|
||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.