Skip to content

Commit

Permalink
Migrate visualization controls to use references (#30880) (#31294)
Browse files Browse the repository at this point in the history
* Migrate visualization controls to use references

* Apply PR feedback
  • Loading branch information
mikecote authored Feb 15, 2019
1 parent b2987ac commit 73c6999
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 26 deletions.
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\\""`
);
});
});

0 comments on commit 73c6999

Please sign in to comment.