Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.x] Migrate visualization controls to use references (#30880) #31294

Merged
merged 1 commit into from
Feb 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions src/legacy/core_plugins/kibana/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,33 @@ export const migrations = {
delete doc.attributes.savedSearchId;
}

// Migrate controls
const visStateJSON = get(doc, 'attributes.visState');
if (visStateJSON) {
let visState;
try {
visState = JSON.parse(visStateJSON);
} catch (e) {
// Let it go, the data is invalid and we'll leave it as is
}
if (visState) {
const controls = get(visState, 'params.controls') || [];
controls.forEach((control, i) => {
if (!control.indexPattern) {
return;
}
control.indexPatternRefName = `control_${i}_index_pattern`;
doc.references.push({
name: control.indexPatternRefName,
type: 'index-pattern',
id: control.indexPattern,
});
delete control.indexPattern;
});
doc.attributes.visState = JSON.stringify(visState);
}
}

// Migrate table splits
try {
const visState = JSON.parse(doc.attributes.visState);
Expand Down
46 changes: 45 additions & 1 deletion src/legacy/core_plugins/kibana/migrations.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,50 @@ Object {
/* eslint-enable max-len */
});

it('extracts index patterns from controls', () => {
const doc = {
id: '1',
type: 'visualization',
attributes: {
foo: true,
visState: JSON.stringify({
bar: false,
params: {
controls: [
{
bar: true,
indexPattern: 'pattern*',
},
{
foo: true,
},
],
},
}),
},
};
const migratedDoc = migrate(doc);
/* eslint-disable max-len */
expect(migratedDoc).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"foo": true,
"visState": "{\\"bar\\":false,\\"params\\":{\\"controls\\":[{\\"bar\\":true,\\"indexPatternRefName\\":\\"control_0_index_pattern\\"},{\\"foo\\":true}]}}",
},
"id": "1",
"references": Array [
Object {
"id": "pattern*",
"name": "control_0_index_pattern",
"type": "index-pattern",
},
],
"type": "visualization",
}
`);
/* eslint-enable max-len */
});

it('skips extracting savedSearchId when missing', () => {
const doc = {
id: '1',
Expand Down Expand Up @@ -1157,7 +1201,7 @@ Object {
"type": "search",
}
`);
/* eslint-enable max-len */
/* eslint-enable max-len */
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,34 +18,66 @@
*/

export function extractReferences({ attributes, references = [] }) {
if (!attributes.savedSearchId) {
return { attributes, references };
const updatedAttributes = { ...attributes };
const updatedReferences = [...references];

// Extract saved search
if (updatedAttributes.savedSearchId) {
updatedReferences.push({
name: 'search_0',
type: 'search',
id: updatedAttributes.savedSearchId,
});
delete updatedAttributes.savedSearchId;
updatedAttributes.savedSearchRefName = 'search_0';
}

// Extract index patterns from controls
if (updatedAttributes.visState) {
const visState = JSON.parse(updatedAttributes.visState);
const controls = visState.params && visState.params.controls || [];
controls.forEach((control, i) => {
if (!control.indexPattern) {
return;
}
control.indexPatternRefName = `control_${i}_index_pattern`;
updatedReferences.push({
name: control.indexPatternRefName,
type: 'index-pattern',
id: control.indexPattern,
});
delete control.indexPattern;
});
updatedAttributes.visState = JSON.stringify(visState);
}

return {
references: [
...references,
{
type: 'search',
name: 'search_0',
id: attributes.savedSearchId,
},
],
attributes: {
...attributes,
savedSearchId: undefined,
savedSearchRefName: 'search_0',
},
references: updatedReferences,
attributes: updatedAttributes,
};
}

export function injectReferences(savedObject, references) {
if (!savedObject.savedSearchRefName) {
return;
if (savedObject.savedSearchRefName) {
const savedSearchReference = references.find(reference => reference.name === savedObject.savedSearchRefName);
if (!savedSearchReference) {
throw new Error(`Could not find saved search reference "${savedObject.savedSearchRefName}"`);
}
savedObject.savedSearchId = savedSearchReference.id;
delete savedObject.savedSearchRefName;
}
const reference = references.find(reference => reference.name === savedObject.savedSearchRefName);
if (!reference) {
throw new Error(`Could not find reference "${savedObject.savedSearchRefName}"`);
if (savedObject.visState) {
const controls = (savedObject.visState.params && savedObject.visState.params.controls) || [];
controls.forEach((control) => {
if (!control.indexPatternRefName) {
return;
}
const reference = references.find(reference => reference.name === control.indexPatternRefName);
if (!reference) {
throw new Error (`Could not find index pattern reference "${control.indexPatternRefName}"`);
}
control.indexPattern = reference.id;
delete control.indexPatternRefName;
});
}
savedObject.savedSearchId = reference.id;
delete savedObject.savedSearchRefName;
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ Object {
Object {
"attributes": Object {
"foo": true,
"savedSearchId": undefined,
"savedSearchRefName": "search_0",
},
"references": Array [
Expand All @@ -64,6 +63,46 @@ Object {
}
`);
});

test('extracts references from controls', () => {
const doc = {
id: '1',
attributes: {
foo: true,
visState: JSON.stringify({
params: {
controls: [
{
bar: true,
indexPattern: 'pattern*',
},
{
bar: false,
},
],
},
}),
},
};
const updatedDoc = extractReferences(doc);
/* eslint-disable max-len */
expect(updatedDoc).toMatchInlineSnapshot(`
Object {
"attributes": Object {
"foo": true,
"visState": "{\\"params\\":{\\"controls\\":[{\\"bar\\":true,\\"indexPatternRefName\\":\\"control_0_index_pattern\\"},{\\"bar\\":false}]}}",
},
"references": Array [
Object {
"id": "pattern*",
"name": "control_0_index_pattern",
"type": "index-pattern",
},
],
}
`);
/* eslint-enable max-len */
});
});

describe('injectReferences', () => {
Expand All @@ -86,32 +125,82 @@ Object {
id: '1',
foo: true,
savedSearchRefName: 'search_0',
visState: {
params: {
controls: [
{
foo: true,
indexPatternRefName: 'control_0_index_pattern',
},
{
foo: false,
},
],
},
},
};
const references = [
{
name: 'search_0',
type: 'search',
id: '123',
},
{
name: 'control_0_index_pattern',
type: 'index-pattern',
id: 'pattern*',
},
];
injectReferences(context, references);
expect(context).toMatchInlineSnapshot(`
Object {
"foo": true,
"id": "1",
"savedSearchId": "123",
"visState": Object {
"params": Object {
"controls": Array [
Object {
"foo": true,
"indexPattern": "pattern*",
},
Object {
"foo": false,
},
],
},
},
}
`);
});

test(`fails when it can't find the reference in the array`, () => {
test(`fails when it can't find the saved search reference in the array`, () => {
const context = {
id: '1',
foo: true,
savedSearchRefName: 'search_0',
};
expect(() => injectReferences(context, [])).toThrowErrorMatchingInlineSnapshot(
`"Could not find reference \\"search_0\\""`
`"Could not find saved search reference \\"search_0\\""`
);
});

test(`fails when it can't find the index pattern reference in the array`, () => {
const context = {
id: '1',
visState: {
params: {
controls: [
{
foo: true,
indexPatternRefName: 'control_0_index_pattern',
},
],
},
},
};
expect(() => injectReferences(context, [])).toThrowErrorMatchingInlineSnapshot(
`"Could not find index pattern reference \\"control_0_index_pattern\\""`
);
});
});