- {requestError ? (
-
- ) : noResults ? (
+ {noResults ? (
) : (
void;
uiState: PersistedState;
- vis: Vis;
+ vis: ExprVis;
visData: any;
visParams: any;
listenOnChange: boolean;
@@ -40,10 +40,9 @@ class VisualizationChart extends React.Component {
private chartDiv = React.createRef();
private containerDiv = React.createRef();
private renderSubject: Rx.Subject<{
- vis: Vis;
+ vis: ExprVis;
visParams: any;
visData: any;
- container: HTMLElement;
}>;
private renderSubscription: Rx.Subscription;
@@ -54,11 +53,9 @@ class VisualizationChart extends React.Component {
const render$ = this.renderSubject.asObservable().pipe(share());
const success$ = render$.pipe(
- filter(
- ({ vis, visData, container }) => vis && container && (!vis.type.requiresSearch || visData)
- ),
+ filter(({ vis, visData }) => vis && (!vis.type.requiresSearch || visData)),
debounceTime(100),
- switchMap(async ({ vis, visData, visParams, container }) => {
+ switchMap(async ({ vis, visData, visParams }) => {
if (!this.visualization) {
// This should never happen, since we only should trigger another rendering
// after this component has mounted and thus the visualization implementation
@@ -66,15 +63,11 @@ class VisualizationChart extends React.Component {
throw new Error('Visualization implementation was not initialized on first render.');
}
- vis.size = [container.clientWidth, container.clientHeight];
- const status = getUpdateStatus(vis.type.requiresUpdateStatus, this, this.props);
- return this.visualization.render(visData, visParams, status);
+ return this.visualization.render(visData, visParams);
})
);
- const requestError$ = render$.pipe(filter(({ vis }) => vis.requestError));
-
- this.renderSubscription = Rx.merge(success$, requestError$).subscribe(() => {
+ this.renderSubscription = success$.subscribe(() => {
if (this.props.onInit) {
this.props.onInit();
}
@@ -145,7 +138,6 @@ class VisualizationChart extends React.Component {
vis: this.props.vis,
visData: this.props.visData,
visParams: this.props.visParams,
- container: this.containerDiv.current,
});
}
}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts
index 51d839275fd27..05ce68221eaf0 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/get_index_pattern.ts
@@ -28,18 +28,18 @@ import { getUISettings, getSavedObjects } from '../services';
export async function getIndexPattern(
savedVis: VisSavedObject
): Promise {
- if (savedVis.vis.type.name !== 'metrics') {
- return savedVis.vis.indexPattern;
+ if (savedVis.visState.type !== 'metrics') {
+ return savedVis.searchSource!.getField('index');
}
const savedObjectsClient = getSavedObjects().client;
const defaultIndex = getUISettings().get('defaultIndex');
- if (savedVis.vis.params.index_pattern) {
+ if (savedVis.visState.params.index_pattern) {
const indexPatternObjects = await savedObjectsClient.find({
type: 'index-pattern',
fields: ['title', 'fields'],
- search: `"${savedVis.vis.params.index_pattern}"`,
+ search: `"${savedVis.visState.params.index_pattern}"`,
searchFields: ['title'],
});
const [indexPattern] = indexPatternObjects.savedObjects.map(indexPatterns.getFromSavedObject);
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts
index c45e6832dc836..342824bade3dd 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts
@@ -45,13 +45,12 @@ import { PersistedState } from '../../../../../../../plugins/visualizations/publ
import { buildPipeline } from '../legacy/build_pipeline';
import { Vis } from '../vis';
import { getExpressions, getUiActions } from '../services';
-import { VisSavedObject } from '../types';
import { VIS_EVENT_TO_TRIGGER } from './events';
const getKeys = (o: T): Array => Object.keys(o) as Array;
export interface VisualizeEmbeddableConfiguration {
- savedVisualization: VisSavedObject;
+ vis: Vis;
indexPatterns?: IIndexPattern[];
editUrl: string;
editable: boolean;
@@ -73,7 +72,6 @@ export interface VisualizeInput extends EmbeddableInput {
export interface VisualizeOutput extends EmbeddableOutput {
editUrl: string;
indexPatterns?: IIndexPattern[];
- savedObjectId: string;
visTypeName: string;
}
@@ -81,9 +79,6 @@ type ExpressionLoader = InstanceType;
export class VisualizeEmbeddable extends Embeddable {
private handler?: ExpressionLoader;
- private savedVisualization: VisSavedObject;
- private appState: { save(): void } | undefined;
- private uiState: PersistedState;
private timefilter: TimefilterContract;
private timeRange?: TimeRange;
private query?: Query;
@@ -99,49 +94,24 @@ export class VisualizeEmbeddable extends Embeddable {
@@ -184,16 +154,16 @@ export class VisualizeEmbeddable extends Embeddable {
- this.uiState.set(key, visCustomizations[key]);
+ this.vis.uiState.set(key, visCustomizations[key]);
});
- this.uiState.on('change', this.uiStateChangeHandler);
+ this.vis.uiState.on('change', this.uiStateChangeHandler);
}
- } else if (!this.appState) {
- this.uiState.clearAllKeys();
+ } else if (this.parent) {
+ this.vis.uiState.clearAllKeys();
}
}
@@ -227,8 +197,8 @@ export class VisualizeEmbeddable extends Embeddable {
+ const visTypesWithoutInspector = [
+ 'markdown',
+ 'input_control_vis',
+ 'metrics',
+ 'vega',
+ 'timelion',
+ ];
+ if (visTypesWithoutInspector.includes(this.vis.type.name)) {
+ return false;
+ }
+ return this.getInspectorAdapters();
+ };
+
/**
*
* @param {Element} domNode
@@ -245,26 +231,6 @@ export class VisualizeEmbeddable extends Embeddable {
- const visTypesWithoutInspector = [
- 'markdown',
- 'input_control_vis',
- 'metrics',
- 'vega',
- 'timelion',
- ];
- if (visTypesWithoutInspector.includes(this.vis.type.name)) {
- return false;
- }
- return this.getInspectorAdapters();
- };
-
- this.vis.openInspector = this.openInspector;
-
const div = document.createElement('div');
div.className = `visualize panel-content panel-content--fullWidth`;
domNode.appendChild(div);
@@ -277,12 +243,12 @@ export class VisualizeEmbeddable extends Embeddable {
// maps hack, remove once esaggs function is cleaned up and ready to accept variables
if (event.name === 'bounds') {
- const agg = this.vis.getAggConfig().aggs.find((a: any) => {
+ const agg = this.vis.data.aggs!.aggs.find((a: any) => {
return get(a, 'type.dslName') === 'geohash_grid';
});
if (
- agg.params.precision !== event.data.precision ||
- !_.isEqual(agg.params.boundingBox, event.data.boundingBox)
+ (agg && agg.params.precision !== event.data.precision) ||
+ (agg && !_.isEqual(agg.params.boundingBox, event.data.boundingBox))
) {
agg.params.boundingBox = event.data.boundingBox;
agg.params.precision = event.data.precision;
@@ -296,7 +262,7 @@ export class VisualizeEmbeddable extends Embeddable s.unsubscribe());
- this.uiState.off('change', this.uiStateChangeHandler);
- this.savedVisualization.vis.removeListener('reload', this.reload);
- this.savedVisualization.vis.removeListener('update', this.handleVisUpdate);
- this.savedVisualization.destroy();
+ this.vis.uiState.off('change', this.uiStateChangeHandler);
+
if (this.handler) {
this.handler.destroy();
this.handler.getElement().remove();
@@ -361,35 +325,25 @@ export class VisualizeEmbeddable extends Embeddable {
- if (this.appState) {
- this.appState.save();
- }
-
this.updateHandler();
};
private uiStateChangeHandler = () => {
this.updateInput({
- ...this.uiState.toJSON(),
+ ...this.vis.uiState.toJSON(),
});
};
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable_factory.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable_factory.tsx
index 1cd97115ee10e..911f5530e97e3 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable_factory.tsx
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable_factory.tsx
@@ -26,9 +26,8 @@ import {
ErrorEmbeddable,
} from '../../../../../../../plugins/embeddable/public';
import { DisabledLabEmbeddable } from './disabled_lab_embeddable';
-import { getIndexPattern } from './get_index_pattern';
import { VisualizeEmbeddable, VisualizeInput, VisualizeOutput } from './visualize_embeddable';
-import { VisSavedObject } from '../types';
+import { Vis } from '../types';
import { VISUALIZE_EMBEDDABLE_TYPE } from './constants';
import {
getCapabilities,
@@ -39,6 +38,7 @@ import {
getTimeFilter,
} from '../services';
import { showNewVisModal } from '../wizard';
+import { convertToSerializedVis } from '../saved_visualizations/_saved_vis';
interface VisualizationAttributes extends SavedObjectAttributes {
visState: string;
@@ -94,31 +94,31 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
}
public async createFromObject(
- savedObject: VisSavedObject,
+ vis: Vis,
input: Partial & { id: string },
parent?: Container
): Promise {
const savedVisualizations = getSavedVisualizationsLoader();
try {
- const visId = savedObject.id as string;
+ const visId = vis.id as string;
const editUrl = visId
? getHttp().basePath.prepend(`/app/kibana${savedVisualizations.urlFor(visId)}`)
: '';
const isLabsEnabled = getUISettings().get('visualize:enableLabs');
- if (!isLabsEnabled && savedObject.vis.type.stage === 'experimental') {
- return new DisabledLabEmbeddable(savedObject.title, input);
+ if (!isLabsEnabled && vis.type.stage === 'experimental') {
+ return new DisabledLabEmbeddable(vis.title, input);
}
- const indexPattern = await getIndexPattern(savedObject);
+ const indexPattern = vis.data.indexPattern;
const indexPatterns = indexPattern ? [indexPattern] : [];
const editable = await this.isEditable();
return new VisualizeEmbeddable(
getTimeFilter(),
{
- savedVisualization: savedObject,
+ vis,
indexPatterns,
editUrl,
editable,
@@ -143,7 +143,8 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
try {
const savedObject = await savedVisualizations.get(savedObjectId);
- return this.createFromObject(savedObject, input, parent);
+ const vis = new Vis(savedObject.visState.type, await convertToSerializedVis(savedObject));
+ return this.createFromObject(vis, input, parent);
} catch (e) {
console.error(e); // eslint-disable-line no-console
return new ErrorEmbeddable(e, input, parent);
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.ts
similarity index 67%
rename from src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js
rename to src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.ts
index a891140677d60..3b0458a6c8dcc 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.js
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/vis.ts
@@ -32,25 +32,47 @@ import _ from 'lodash';
import { PersistedState } from '../../../../../../../plugins/visualizations/public';
import { getTypes } from '../services';
+import { VisType } from '../vis_types';
+import { VisParams } from '../types';
-export class Vis extends EventEmitter {
- constructor(visState = { type: 'histogram' }) {
+export interface ExprVisState {
+ title?: string;
+ type: VisType | string;
+ params?: VisParams;
+}
+
+export interface ExprVisAPIEvents {
+ filter: (data: any) => void;
+ brush: (data: any) => void;
+}
+
+export interface ExprVisAPI {
+ events: ExprVisAPIEvents;
+}
+
+export class ExprVis extends EventEmitter {
+ public title: string = '';
+ public type: VisType;
+ public params: VisParams = {};
+ public sessionState: Record = {};
+ public API: ExprVisAPI;
+ public eventsSubject: any;
+ private uiState: PersistedState;
+
+ constructor(visState: ExprVisState = { type: 'histogram' }) {
super();
- this._setUiState(new PersistedState());
+ this.type = this.getType(visState.type);
+ this.uiState = new PersistedState();
this.setState(visState);
- // Session state is for storing information that is transitory, and will not be saved with the visualization.
- // For instance, map bounds, which depends on the view port, browser window size, etc.
- this.sessionState = {};
-
this.API = {
events: {
- filter: data => {
+ filter: (data: any) => {
if (!this.eventsSubject) return;
this.eventsSubject.next({ name: 'filterBucket', data });
},
- brush: data => {
+ brush: (data: any) => {
if (!this.eventsSubject) return;
this.eventsSubject.next({ name: 'brush', data });
},
@@ -58,18 +80,22 @@ export class Vis extends EventEmitter {
};
}
- setState(state) {
- this.title = state.title || '';
- const type = state.type || this.type;
+ private getType(type: string | VisType) {
if (_.isString(type)) {
- this.type = getTypes().get(type);
+ return getTypes().get(type);
if (!this.type) {
throw new Error(`Invalid type "${type}"`);
}
} else {
- this.type = type;
+ return type;
}
+ }
+ setState(state: ExprVisState) {
+ this.title = state.title || '';
+ if (state.type) {
+ this.type = this.getType(state.type);
+ }
this.params = _.defaultsDeep(
{},
_.cloneDeep(state.params || {}),
@@ -77,10 +103,6 @@ export class Vis extends EventEmitter {
);
}
- setCurrentState(state) {
- this.setState(state);
- }
-
getState() {
return {
title: this.title,
@@ -106,34 +128,27 @@ export class Vis extends EventEmitter {
}
hasUiState() {
- return !!this.__uiState;
+ return !!this.uiState;
}
- /***
- * this should not be used outside of visualize
- * @param uiState
- * @private
- */
- _setUiState(uiState) {
- if (uiState instanceof PersistedState) {
- this.__uiState = uiState;
- }
+ getUiState() {
+ return this.uiState;
}
- getUiState() {
- return this.__uiState;
+ setUiState(state: PersistedState) {
+ this.uiState = state;
}
/**
* Currently this is only used to extract map-specific information
* (e.g. mapZoom, mapCenter).
*/
- uiStateVal(key, val) {
+ uiStateVal(key: string, val: any) {
if (this.hasUiState()) {
if (_.isUndefined(val)) {
- return this.__uiState.get(key);
+ return this.uiState.get(key);
}
- return this.__uiState.set(key, val);
+ return this.uiState.set(key, val);
}
return val;
}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx
index 02a31447d23c1..0fd81c753da24 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/expressions/visualization_renderer.tsx
@@ -20,8 +20,9 @@
import React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
// @ts-ignore
-import { Vis } from './vis';
+import { ExprVis } from './vis';
import { Visualization } from '../components';
+import { VisParams } from '../types';
export const visualization = () => ({
name: 'visualization',
@@ -31,9 +32,9 @@ export const visualization = () => ({
const { visData, visConfig, params } = config;
const visType = config.visType || visConfig.type;
- const vis = new Vis({
- type: visType,
- params: visConfig,
+ const vis = new ExprVis({
+ type: visType as string,
+ params: visConfig as VisParams,
});
vis.eventsSubject = { next: handlers.event };
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts
index b59eb2277411c..078cc4a3f4035 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/index.ts
@@ -39,12 +39,11 @@ export { VisualizationsSetup, VisualizationsStart };
/** @public types */
export { VisTypeAlias, VisType } from './vis_types';
export { VisSavedObject } from './types';
-export { Vis, VisParams, VisState } from './vis';
+export { Vis, VisParams, SerializedVis, SerializedVisData, VisData } from './vis';
import { VisualizeEmbeddableFactory, VisualizeEmbeddable } from './embeddable';
export type VisualizeEmbeddableFactoryContract = PublicContract;
export type VisualizeEmbeddableContract = PublicContract;
export { TypesService } from './vis_types/types_service';
-export { Status } from './legacy/update_status'; // should remove
export { VISUALIZE_EMBEDDABLE_TYPE, VisualizeInput } from './embeddable';
export { SchemaConfig } from './legacy/build_pipeline';
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts
index 9446069182e19..d5c532b53a53e 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.test.ts
@@ -27,7 +27,7 @@ import {
Schemas,
} from './build_pipeline';
import { Vis } from '..';
-import { searchSourceMock, dataPluginMock } from '../../../../../../../plugins/data/public/mocks';
+import { dataPluginMock } from '../../../../../../../plugins/data/public/mocks';
import { IAggConfig } from '../../../../../../../plugins/data/public';
jest.mock('ui/new_platform');
@@ -78,19 +78,11 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
});
describe('buildPipelineVisFunction', () => {
- let visStateDef: ReturnType;
let schemaConfig: SchemaConfig;
let schemasDef: Schemas;
let uiState: any;
beforeEach(() => {
- visStateDef = {
- title: 'title',
- // @ts-ignore
- type: 'type',
- params: {},
- } as ReturnType;
-
schemaConfig = {
accessor: 0,
label: '',
@@ -105,66 +97,53 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
it('handles vega function', () => {
const vis = {
- ...visStateDef,
params: { spec: 'this is a test' },
};
- const actual = buildPipelineVisFunction.vega(vis, schemasDef, uiState);
+ const actual = buildPipelineVisFunction.vega(vis.params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
it('handles input_control_vis function', () => {
- const visState = {
- ...visStateDef,
- params: {
- some: 'nested',
- data: { here: true },
- },
+ const params = {
+ some: 'nested',
+ data: { here: true },
};
- const actual = buildPipelineVisFunction.input_control_vis(visState, schemasDef, uiState);
+ const actual = buildPipelineVisFunction.input_control_vis(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
it('handles metrics/tsvb function', () => {
- const visState = { ...visStateDef, params: { foo: 'bar' } };
- const actual = buildPipelineVisFunction.metrics(visState, schemasDef, uiState);
+ const params = { foo: 'bar' };
+ const actual = buildPipelineVisFunction.metrics(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
it('handles timelion function', () => {
- const visState = {
- ...visStateDef,
- params: { expression: 'foo', interval: 'bar' },
- };
- const actual = buildPipelineVisFunction.timelion(visState, schemasDef, uiState);
+ const params = { expression: 'foo', interval: 'bar' };
+ const actual = buildPipelineVisFunction.timelion(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
it('handles markdown function', () => {
- const visState = {
- ...visStateDef,
- params: {
- markdown: '## hello _markdown_',
- fontSize: 12,
- openLinksInNewTab: true,
- foo: 'bar',
- },
+ const params = {
+ markdown: '## hello _markdown_',
+ fontSize: 12,
+ openLinksInNewTab: true,
+ foo: 'bar',
};
- const actual = buildPipelineVisFunction.markdown(visState, schemasDef, uiState);
+ const actual = buildPipelineVisFunction.markdown(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
it('handles undefined markdown function', () => {
- const visState = {
- ...visStateDef,
- params: { fontSize: 12, openLinksInNewTab: true, foo: 'bar' },
- };
- const actual = buildPipelineVisFunction.markdown(visState, schemasDef, uiState);
+ const params = { fontSize: 12, openLinksInNewTab: true, foo: 'bar' };
+ const actual = buildPipelineVisFunction.markdown(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
describe('handles table function', () => {
it('without splits or buckets', () => {
- const visState = { ...visStateDef, params: { foo: 'bar' } };
+ const params = { foo: 'bar' };
const schemas = {
...schemasDef,
metric: [
@@ -172,22 +151,22 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
{ ...schemaConfig, accessor: 1 },
],
};
- const actual = buildPipelineVisFunction.table(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.table(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with splits', () => {
- const visState = { ...visStateDef, params: { foo: 'bar' } };
+ const params = { foo: 'bar' };
const schemas = {
...schemasDef,
split_row: [1, 2],
};
- const actual = buildPipelineVisFunction.table(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.table(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with splits and buckets', () => {
- const visState = { ...visStateDef, params: { foo: 'bar' } };
+ const params = { foo: 'bar' };
const schemas = {
...schemasDef,
metric: [
@@ -197,17 +176,14 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
split_row: [2, 4],
bucket: [3],
};
- const actual = buildPipelineVisFunction.table(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.table(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with showPartialRows=true and showMetricsAtAllLevels=true', () => {
- const visState = {
- ...visStateDef,
- params: {
- showMetricsAtAllLevels: true,
- showPartialRows: true,
- },
+ const params = {
+ showMetricsAtAllLevels: true,
+ showPartialRows: true,
};
const schemas = {
...schemasDef,
@@ -219,17 +195,14 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
],
bucket: [0, 3],
};
- const actual = buildPipelineVisFunction.table(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.table(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with showPartialRows=true and showMetricsAtAllLevels=false', () => {
- const visState = {
- ...visStateDef,
- params: {
- showMetricsAtAllLevels: false,
- showPartialRows: true,
- },
+ const params = {
+ showMetricsAtAllLevels: false,
+ showPartialRows: true,
};
const schemas = {
...schemasDef,
@@ -241,14 +214,14 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
],
bucket: [0, 3],
};
- const actual = buildPipelineVisFunction.table(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.table(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
});
describe('handles metric function', () => {
it('without buckets', () => {
- const visState = { ...visStateDef, params: { metric: {} } };
+ const params = { metric: {} };
const schemas = {
...schemasDef,
metric: [
@@ -256,12 +229,12 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
{ ...schemaConfig, accessor: 1 },
],
};
- const actual = buildPipelineVisFunction.metric(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.metric(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with buckets', () => {
- const visState = { ...visStateDef, params: { metric: {} } };
+ const params = { metric: {} };
const schemas = {
...schemasDef,
metric: [
@@ -270,21 +243,21 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
],
group: [{ accessor: 2 }],
};
- const actual = buildPipelineVisFunction.metric(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.metric(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with percentage mode should have percentage format', () => {
- const visState = { ...visStateDef, params: { metric: { percentageMode: true } } };
+ const params = { metric: { percentageMode: true } };
const schemas = { ...schemasDef };
- const actual = buildPipelineVisFunction.metric(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.metric(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
});
describe('handles tagcloud function', () => {
it('without buckets', () => {
- const actual = buildPipelineVisFunction.tagcloud(visStateDef, schemasDef, uiState);
+ const actual = buildPipelineVisFunction.tagcloud({}, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
@@ -293,21 +266,21 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
...schemasDef,
segment: [{ accessor: 1 }],
};
- const actual = buildPipelineVisFunction.tagcloud(visStateDef, schemas, uiState);
+ const actual = buildPipelineVisFunction.tagcloud({}, schemas, uiState);
expect(actual).toMatchSnapshot();
});
it('with boolean param showLabel', () => {
- const visState = { ...visStateDef, params: { showLabel: false } };
- const actual = buildPipelineVisFunction.tagcloud(visState, schemasDef, uiState);
+ const params = { showLabel: false };
+ const actual = buildPipelineVisFunction.tagcloud(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
});
describe('handles region_map function', () => {
it('without buckets', () => {
- const visState = { ...visStateDef, params: { metric: {} } };
- const actual = buildPipelineVisFunction.region_map(visState, schemasDef, uiState);
+ const params = { metric: {} };
+ const actual = buildPipelineVisFunction.region_map(params, schemasDef, uiState);
expect(actual).toMatchSnapshot();
});
@@ -316,19 +289,19 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
...schemasDef,
segment: [1, 2],
};
- const actual = buildPipelineVisFunction.region_map(visStateDef, schemas, uiState);
+ const actual = buildPipelineVisFunction.region_map({}, schemas, uiState);
expect(actual).toMatchSnapshot();
});
});
it('handles tile_map function', () => {
- const visState = { ...visStateDef, params: { metric: {} } };
+ const params = { metric: {} };
const schemas = {
...schemasDef,
segment: [1, 2],
geo_centroid: [3, 4],
};
- const actual = buildPipelineVisFunction.tile_map(visState, schemas, uiState);
+ const actual = buildPipelineVisFunction.tile_map(params, schemas, uiState);
expect(actual).toMatchSnapshot();
});
@@ -337,7 +310,7 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
...schemasDef,
segment: [1, 2],
};
- const actual = buildPipelineVisFunction.pie(visStateDef, schemas, uiState);
+ const actual = buildPipelineVisFunction.pie({}, schemas, uiState);
expect(actual).toMatchSnapshot();
});
});
@@ -347,11 +320,16 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
it('calls toExpression on vis_type if it exists', async () => {
const vis = ({
- getCurrentState: () => {},
- getUiState: () => null,
+ getState: () => {},
isHierarchical: () => false,
- aggs: {
- getResponseAggs: () => [],
+ data: {
+ aggs: {
+ getResponseAggs: () => [],
+ },
+ searchSource: {
+ getField: jest.fn(),
+ getParent: jest.fn(),
+ },
},
// @ts-ignore
type: {
@@ -359,7 +337,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
},
} as unknown) as Vis;
const expression = await buildPipeline(vis, {
- searchSource: searchSourceMock,
timefilter: dataStart.query.timefilter.timefilter,
});
expect(expression).toMatchSnapshot();
@@ -370,7 +347,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
const dataStart = dataPluginMock.createStartContract();
let aggs: IAggConfig[];
- let visState: any;
let vis: Vis;
let params: any;
@@ -397,7 +373,11 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
describe('test y dimension format for histogram chart', () => {
beforeEach(() => {
- visState = {
+ vis = {
+ // @ts-ignore
+ type: {
+ name: 'histogram',
+ },
params: {
seriesParams: [
{
@@ -414,24 +394,16 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
},
],
},
- };
-
- vis = {
- // @ts-ignore
- type: {
- name: 'histogram',
- },
- aggs: {
- getResponseAggs: () => {
- return aggs;
- },
+ data: {
+ aggs: {
+ getResponseAggs: () => {
+ return aggs;
+ },
+ } as any,
},
isHierarchical: () => {
return false;
},
- getCurrentState: () => {
- return visState;
- },
};
});
@@ -443,7 +415,7 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
});
it('with one numeric metric in percentage mode', async () => {
- visState.params.valueAxes[0].scale.mode = 'percentage';
+ vis.params.valueAxes[0].scale.mode = 'percentage';
const dimensions = await buildVislibDimensions(vis, params);
const expected = { id: 'percent' };
const actual = dimensions.y[0].format;
@@ -454,33 +426,31 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
const aggConfig = aggs[0];
aggs = [{ ...aggConfig } as IAggConfig, { ...aggConfig, id: '5' } as IAggConfig];
- visState = {
- params: {
- seriesParams: [
- {
- data: { id: '0' },
- valueAxis: 'axis-y-1',
- },
- {
- data: { id: '5' },
- valueAxis: 'axis-y-2',
- },
- ],
- valueAxes: [
- {
- id: 'axis-y-1',
- scale: {
- mode: 'normal',
- },
+ vis.params = {
+ seriesParams: [
+ {
+ data: { id: '0' },
+ valueAxis: 'axis-y-1',
+ },
+ {
+ data: { id: '5' },
+ valueAxis: 'axis-y-2',
+ },
+ ],
+ valueAxes: [
+ {
+ id: 'axis-y-1',
+ scale: {
+ mode: 'normal',
},
- {
- id: 'axis-y-2',
- scale: {
- mode: 'percentage',
- },
+ },
+ {
+ id: 'axis-y-2',
+ scale: {
+ mode: 'percentage',
},
- ],
- },
+ },
+ ],
};
const dimensions = await buildVislibDimensions(vis, params);
@@ -493,29 +463,27 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
describe('test y dimension format for gauge chart', () => {
beforeEach(() => {
- visState = { params: { gauge: {} } };
-
vis = {
// @ts-ignore
type: {
name: 'gauge',
},
- aggs: {
- getResponseAggs: () => {
- return aggs;
- },
+ params: { gauge: {} },
+ data: {
+ aggs: {
+ getResponseAggs: () => {
+ return aggs;
+ },
+ } as any,
},
isHierarchical: () => {
return false;
},
- getCurrentState: () => {
- return visState;
- },
};
});
it('with percentageMode = false', async () => {
- visState.params.gauge.percentageMode = false;
+ vis.params.gauge.percentageMode = false;
const dimensions = await buildVislibDimensions(vis, params);
const expected = { id: 'number' };
const actual = dimensions.y[0].format;
@@ -523,7 +491,7 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
});
it('with percentageMode = true', async () => {
- visState.params.gauge.percentageMode = true;
+ vis.params.gauge.percentageMode = true;
const dimensions = await buildVislibDimensions(vis, params);
const expected = { id: 'percent' };
const actual = dimensions.y[0].format;
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts
index de974e6e969ef..ea15cd9201fd7 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/build_pipeline.ts
@@ -21,14 +21,13 @@ import { get } from 'lodash';
import moment from 'moment';
import { SerializedFieldFormat } from '../../../../../../../plugins/expressions/public';
import {
- fieldFormats,
IAggConfig,
- ISearchSource,
+ fieldFormats,
search,
TimefilterContract,
} from '../../../../../../../plugins/data/public';
-const { isDateHistogramBucketAggConfig } = search.aggs;
import { Vis, VisParams } from '../types';
+const { isDateHistogramBucketAggConfig } = search.aggs;
interface SchemaConfigParams {
precision?: number;
@@ -59,7 +58,7 @@ export interface Schemas {
}
type buildVisFunction = (
- visState: ReturnType,
+ params: VisParams,
schemas: Schemas,
uiState: any,
meta?: { savedObjectId?: string }
@@ -139,7 +138,12 @@ const getSchemas = (
const schemas: Schemas = {
metric: [],
};
- const responseAggs = vis.aggs.getResponseAggs().filter((agg: IAggConfig) => agg.enabled);
+
+ if (!vis.data.aggs) {
+ return schemas;
+ }
+
+ const responseAggs = vis.data.aggs.getResponseAggs().filter((agg: IAggConfig) => agg.enabled);
const isHierarchical = vis.isHierarchical();
const metrics = responseAggs.filter((agg: IAggConfig) => agg.type.type === 'metrics');
responseAggs.forEach((agg: IAggConfig) => {
@@ -228,9 +232,8 @@ export const prepareDimension = (variable: string, data: any) => {
};
const adjustVislibDimensionFormmaters = (vis: Vis, dimensions: { y: any[] }): void => {
- const visState = vis.getCurrentState();
- const visConfig = visState.params;
- const responseAggs = vis.aggs.getResponseAggs().filter((agg: IAggConfig) => agg.enabled);
+ const visConfig = vis.params;
+ const responseAggs = vis.data.aggs!.getResponseAggs().filter((agg: IAggConfig) => agg.enabled);
(dimensions.y || []).forEach(yDimension => {
const yAgg = responseAggs[yDimension.accessor];
@@ -252,27 +255,26 @@ const adjustVislibDimensionFormmaters = (vis: Vis, dimensions: { y: any[] }): vo
};
export const buildPipelineVisFunction: BuildPipelineVisFunction = {
- vega: visState => {
- return `vega ${prepareString('spec', visState.params.spec)}`;
+ vega: params => {
+ return `vega ${prepareString('spec', params.spec)}`;
},
- input_control_vis: visState => {
- return `input_control_vis ${prepareJson('visConfig', visState.params)}`;
+ input_control_vis: params => {
+ return `input_control_vis ${prepareJson('visConfig', params)}`;
},
- metrics: (visState, schemas, uiState = {}, meta) => {
- const paramsJson = prepareJson('params', visState.params);
+ metrics: (params, schemas, uiState = {}) => {
+ const paramsJson = prepareJson('params', params);
const uiStateJson = prepareJson('uiState', uiState);
- const savedObjectIdParam = prepareString('savedObjectId', meta?.savedObjectId);
- const params = [paramsJson, uiStateJson, savedObjectIdParam].filter(param => Boolean(param));
- return `tsvb ${params.join(' ')}`;
+ const paramsArray = [paramsJson, uiStateJson].filter(param => Boolean(param));
+ return `tsvb ${paramsArray.join(' ')}`;
},
- timelion: visState => {
- const expression = prepareString('expression', visState.params.expression);
- const interval = prepareString('interval', visState.params.interval);
+ timelion: params => {
+ const expression = prepareString('expression', params.expression);
+ const interval = prepareString('interval', params.interval);
return `timelion_vis ${expression}${interval}`;
},
- markdown: visState => {
- const { markdown, fontSize, openLinksInNewTab } = visState.params;
+ markdown: params => {
+ const { markdown, fontSize, openLinksInNewTab } = params;
let escapedMarkdown = '';
if (typeof markdown === 'string' || markdown instanceof String) {
escapedMarkdown = escapeString(markdown.toString());
@@ -282,14 +284,14 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = {
expr += prepareValue('openLinksInNewTab', openLinksInNewTab);
return expr;
},
- table: (visState, schemas) => {
+ table: (params, schemas) => {
const visConfig = {
- ...visState.params,
- ...buildVisConfig.table(schemas, visState.params),
+ ...params,
+ ...buildVisConfig.table(schemas, params),
};
return `kibana_table ${prepareJson('visConfig', visConfig)}`;
},
- metric: (visState, schemas) => {
+ metric: (params, schemas) => {
const {
percentageMode,
useRanges,
@@ -299,11 +301,11 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = {
labels,
invertColors,
style,
- } = visState.params.metric;
+ } = params.metric;
const { metrics, bucket } = buildVisConfig.metric(schemas).dimensions;
// fix formatter for percentage mode
- if (get(visState.params, 'metric.percentageMode') === true) {
+ if (get(params, 'metric.percentageMode') === true) {
metrics.forEach((metric: SchemaConfig) => {
metric.format = { id: 'percent' };
});
@@ -335,8 +337,8 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = {
return expr;
},
- tagcloud: (visState, schemas) => {
- const { scale, orientation, minFontSize, maxFontSize, showLabel } = visState.params;
+ tagcloud: (params, schemas) => {
+ const { scale, orientation, minFontSize, maxFontSize, showLabel } = params;
const { metric, bucket } = buildVisConfig.tagcloud(schemas);
let expr = `tagcloud metric={visdimension ${metric.accessor}} `;
expr += prepareValue('scale', scale);
@@ -348,23 +350,23 @@ export const buildPipelineVisFunction: BuildPipelineVisFunction = {
return expr;
},
- region_map: (visState, schemas) => {
+ region_map: (params, schemas) => {
const visConfig = {
- ...visState.params,
+ ...params,
...buildVisConfig.region_map(schemas),
};
return `regionmap ${prepareJson('visConfig', visConfig)}`;
},
- tile_map: (visState, schemas) => {
+ tile_map: (params, schemas) => {
const visConfig = {
- ...visState.params,
+ ...params,
...buildVisConfig.tile_map(schemas),
};
return `tilemap ${prepareJson('visConfig', visConfig)}`;
},
- pie: (visState, schemas) => {
+ pie: (params, schemas) => {
const visConfig = {
- ...visState.params,
+ ...params,
...buildVisConfig.pie(schemas),
};
return `kibana_pie ${prepareJson('visConfig', visConfig)}`;
@@ -440,7 +442,6 @@ const buildVisConfig: BuildVisConfigFunction = {
export const buildVislibDimensions = async (
vis: any,
params: {
- searchSource: any;
timefilter: TimefilterContract;
timeRange?: any;
abortSignal?: AbortSignal;
@@ -460,7 +461,7 @@ export const buildVislibDimensions = async (
splitColumn: schemas.split_column,
};
if (schemas.segment) {
- const xAgg = vis.aggs.getResponseAggs()[dimensions.x.accessor];
+ const xAgg = vis.data.aggs.getResponseAggs()[dimensions.x.accessor];
if (xAgg.type.name === 'date_histogram') {
dimensions.x.params.date = true;
const { esUnit, esValue } = xAgg.buckets.getInterval();
@@ -472,7 +473,7 @@ export const buildVislibDimensions = async (
} else if (xAgg.type.name === 'histogram') {
const intervalParam = xAgg.type.paramByName('interval');
const output = { params: {} as any };
- await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, params.searchSource, {
+ await intervalParam.modifyAggConfigOnSearchRequestStart(xAgg, vis.data.searchSource, {
abortSignal: params.abortSignal,
});
intervalParam.write(xAgg, output);
@@ -487,18 +488,14 @@ export const buildVislibDimensions = async (
export const buildPipeline = async (
vis: Vis,
params: {
- searchSource: ISearchSource;
timefilter: TimefilterContract;
timeRange?: any;
- savedObjectId?: string;
}
) => {
- const { searchSource } = params;
- const { indexPattern } = vis;
- const query = searchSource.getField('query');
- const filters = searchSource.getField('filter');
- const visState = vis.getCurrentState();
- const uiState = vis.getUiState();
+ const { indexPattern, searchSource } = vis.data;
+ const query = searchSource!.getField('query');
+ const filters = searchSource!.getField('filter');
+ const { uiState } = vis;
// context
let pipeline = `kibana | kibana_context `;
@@ -508,18 +505,18 @@ export const buildPipeline = async (
if (filters) {
pipeline += prepareJson('filters', filters);
}
- if (vis.savedSearchId) {
- pipeline += prepareString('savedSearchId', vis.savedSearchId);
+ if (vis.data.savedSearchId) {
+ pipeline += prepareString('savedSearchId', vis.data.savedSearchId);
}
pipeline += '| ';
// request handler
if (vis.type.requestHandler === 'courier') {
pipeline += `esaggs
- ${prepareString('index', indexPattern.id)}
+ ${prepareString('index', indexPattern!.id)}
metricsAtAllLevels=${vis.isHierarchical()}
partialRows=${vis.type.requiresPartialRows || vis.params.showPartialRows || false}
- ${prepareJson('aggConfigs', visState.aggs)} | `;
+ ${prepareJson('aggConfigs', vis.data.aggs!.aggs)} | `;
}
const schemas = getSchemas(vis, {
@@ -527,18 +524,16 @@ export const buildPipeline = async (
timefilter: params.timefilter,
});
if (buildPipelineVisFunction[vis.type.name]) {
- pipeline += buildPipelineVisFunction[vis.type.name](visState, schemas, uiState, {
- savedObjectId: params.savedObjectId,
- });
+ pipeline += buildPipelineVisFunction[vis.type.name](vis.params, schemas, uiState);
} else if (vislibCharts.includes(vis.type.name)) {
- const visConfig = visState.params;
+ const visConfig = { ...vis.params };
visConfig.dimensions = await buildVislibDimensions(vis, params);
- pipeline += `vislib type='${vis.type.name}' ${prepareJson('visConfig', visState.params)}`;
+ pipeline += `vislib type='${vis.type.name}' ${prepareJson('visConfig', visConfig)}`;
} else if (vis.type.toExpression) {
pipeline += await vis.type.toExpression(vis, params);
} else {
- const visConfig = visState.params;
+ const visConfig = { ...vis.params };
visConfig.dimensions = schemas;
pipeline += `visualization type='${vis.type.name}'
${prepareJson('visConfig', visConfig)}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.test.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.test.js
deleted file mode 100644
index c63a8cd48e625..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.test.js
+++ /dev/null
@@ -1,102 +0,0 @@
-/*
- * 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 { getUpdateStatus, Status } from './update_status';
-
-// Parts of the tests in this file are generated more dynamically, based on the
-// values inside the Status object.Make sure this object has one function per entry
-// in Status, that actually change on the passed $scope, what needs to be changed
-// so that we expect the getUpdateStatus function to actually detect a change.
-const changeFunctions = {
- [Status.AGGS]: $scope => ($scope.vis.aggs = { foo: 'new' }),
- [Status.DATA]: $scope => ($scope.visData = { foo: 'new' }),
- [Status.PARAMS]: $scope => ($scope.vis.params = { foo: 'new' }),
- [Status.RESIZE]: $scope => ($scope.vis.size = [50, 50]),
- [Status.TIME]: $scope => ($scope.vis.filters.timeRange = { from: 'now-7d', to: 'now' }),
- [Status.UI_STATE]: $scope => ($scope.uiState = { foo: 'new' }),
-};
-
-describe('getUpdateStatus', () => {
- function getScope() {
- return {
- vis: {
- aggs: {},
- size: [100, 100],
- params: {},
- filters: {},
- },
- uiState: {},
- visData: {},
- };
- }
-
- function initStatusCheckerAndChangeProperty(type, requiresUpdateStatus) {
- const $scope = getScope();
- // Call the getUpdateStatus function initially, so it can store it's current state
- getUpdateStatus(requiresUpdateStatus, $scope, $scope);
-
- // Get the change function for that specific change type
- const changeFn = changeFunctions[type];
- if (!changeFn) {
- throw new Error(`Please implement the test change function for ${type}.`);
- }
-
- // Call that change function to manipulate the scope so it changed.
- changeFn($scope);
-
- return getUpdateStatus(requiresUpdateStatus, $scope, $scope);
- }
-
- it('should be a function', () => {
- expect(typeof getUpdateStatus).toBe('function');
- });
-
- Object.entries(Status).forEach(([typeKey, typeValue]) => {
- // This block automatically creates very simple tests for each of the Status
- // keys, so we have simple tests per changed property.
- // If it makes sense to test more specific behavior of a specific change detection
- // please add additional tests for that.
-
- it(`should detect changes for Status.${typeKey}`, () => {
- // Check whether the required change type is not correctly determined
- const status = initStatusCheckerAndChangeProperty(typeValue, [typeValue]);
- expect(status[typeValue]).toBe(true);
- });
-
- it(`should not detect changes in other properties when changing Status.${typeKey}`, () => {
- // Only change typeKey, but track changes for all status changes
- const status = initStatusCheckerAndChangeProperty(typeValue, Object.values(Status));
- Object.values(Status)
- // Filter out the actual changed property so we only test for all other properties
- .filter(stat => stat !== typeValue)
- .forEach(otherProp => {
- expect(status[otherProp]).toBeFalsy();
- });
- });
-
- it(`should not detect changes if not requested for Status.${typeKey}`, () => {
- const allOtherStatusProperties = Object.values(Status).filter(stat => stat !== typeValue);
- // Change only the typeKey property, but do not listen for changes on it
- // listen on all other status changes instead.
- const status = initStatusCheckerAndChangeProperty(typeValue, allOtherStatusProperties);
- // The typeValue check should be falsy, since we did not request tracking it.
- expect(status[typeValue]).toBeFalsy();
- });
- });
-});
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts
deleted file mode 100644
index 92a9ce8366f4f..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/legacy/update_status.ts
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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 { PersistedState } from '../../../../../../../plugins/visualizations/public';
-import { calculateObjectHash } from '../../../../../../../plugins/kibana_utils/common';
-import { Vis } from '../vis';
-
-enum Status {
- AGGS = 'aggs',
- DATA = 'data',
- PARAMS = 'params',
- RESIZE = 'resize',
- TIME = 'time',
- UI_STATE = 'uiState',
-}
-
-/**
- * Checks whether the hash of a specific key in the given oldStatus has changed
- * compared to the new valueHash passed.
- */
-function hasHashChanged(
- valueHash: string,
- oldStatus: { [key in T]?: string },
- name: T
-): boolean {
- const oldHash = oldStatus[name];
- return oldHash !== valueHash;
-}
-
-interface Size {
- width: number;
- height: number;
-}
-
-function hasSizeChanged(size: Size, oldSize?: Size): boolean {
- if (!oldSize) {
- return true;
- }
- return oldSize.width !== size.width || oldSize.height !== size.height;
-}
-
-function getUpdateStatus(
- requiresUpdateStatus: T[] = [],
- obj: any,
- param: { vis: Vis; visData: any; uiState: PersistedState }
-): { [reqStats in T]: boolean } {
- const status = {} as { [reqStats in Status]: boolean };
-
- // If the vis type doesn't need update status, skip all calculations
- if (requiresUpdateStatus.length === 0) {
- return status;
- }
-
- if (!obj._oldStatus) {
- obj._oldStatus = {};
- }
-
- for (const requiredStatus of requiresUpdateStatus) {
- let hash;
- // Calculate all required status updates for this visualization
- switch (requiredStatus) {
- case Status.AGGS:
- hash = calculateObjectHash(param.vis.aggs);
- status.aggs = hasHashChanged(hash, obj._oldStatus, 'aggs');
- obj._oldStatus.aggs = hash;
- break;
- case Status.DATA:
- hash = calculateObjectHash(param.visData);
- status.data = hasHashChanged(hash, obj._oldStatus, 'data');
- obj._oldStatus.data = hash;
- break;
- case Status.PARAMS:
- hash = calculateObjectHash(param.vis.params);
- status.params = hasHashChanged(hash, obj._oldStatus, 'param');
- obj._oldStatus.param = hash;
- break;
- case Status.RESIZE:
- const width: number = param.vis.size ? param.vis.size[0] : 0;
- const height: number = param.vis.size ? param.vis.size[1] : 0;
- const size = { width, height };
- status.resize = hasSizeChanged(size, obj._oldStatus.resize);
- obj._oldStatus.resize = size;
- break;
- case Status.TIME:
- const timeRange = param.vis.filters && param.vis.filters.timeRange;
- hash = calculateObjectHash(timeRange);
- status.time = hasHashChanged(hash, obj._oldStatus, 'time');
- obj._oldStatus.time = hash;
- break;
- case Status.UI_STATE:
- hash = calculateObjectHash(param.uiState);
- status.uiState = hasHashChanged(hash, obj._oldStatus, 'uiState');
- obj._oldStatus.uiState = hash;
- break;
- }
- }
-
- return status;
-}
-
-export { getUpdateStatus, Status };
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
index 4ee727e46f4d6..17f777e4e80e1 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts
@@ -41,6 +41,8 @@ const createStartContract = (): VisualizationsStart => ({
savedVisualizationsLoader: {} as any,
showNewVisModal: jest.fn(),
createVis: jest.fn(),
+ convertFromSerializedVis: jest.fn(),
+ convertToSerializedVis: jest.fn(),
});
const createInstance = async () => {
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts
index 953caecefb974..3ade6cee0d4d2 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts
@@ -39,6 +39,8 @@ import {
setSavedVisualizationsLoader,
setTimeFilter,
setAggs,
+ setChrome,
+ setOverlays,
} from './services';
import { VISUALIZE_EMBEDDABLE_TYPE, VisualizeEmbeddableFactory } from './embeddable';
import { ExpressionsSetup, ExpressionsStart } from '../../../../../../plugins/expressions/public';
@@ -48,14 +50,16 @@ import { visualization as visualizationRenderer } from './expressions/visualizat
import {
DataPublicPluginSetup,
DataPublicPluginStart,
- IIndexPattern,
} from '../../../../../../plugins/data/public';
import { UsageCollectionSetup } from '../../../../../../plugins/usage_collection/public';
import { createSavedVisLoader, SavedVisualizationsLoader } from './saved_visualizations';
-import { VisImpl } from './vis_impl';
+import { SerializedVis, Vis } from './vis';
import { showNewVisModal } from './wizard';
import { UiActionsStart } from '../../../../../../plugins/ui_actions/public';
-import { VisState } from './types';
+import {
+ convertFromSerializedVis,
+ convertToSerializedVis,
+} from './saved_visualizations/_saved_vis';
/**
* Interface for this plugin's returned setup/start contracts.
@@ -67,7 +71,9 @@ export type VisualizationsSetup = TypesSetup;
export interface VisualizationsStart extends TypesStart {
savedVisualizationsLoader: SavedVisualizationsLoader;
- createVis: (indexPattern: IIndexPattern, visState?: VisState) => VisImpl;
+ createVis: (visType: string, visState?: SerializedVis) => Vis;
+ convertToSerializedVis: typeof convertToSerializedVis;
+ convertFromSerializedVis: typeof convertFromSerializedVis;
showNewVisModal: typeof showNewVisModal;
}
@@ -138,6 +144,8 @@ export class VisualizationsPlugin
setUiActions(uiActions);
setTimeFilter(data.query.timefilter.timefilter);
setAggs(data.search.aggs);
+ setOverlays(core.overlays);
+ setChrome(core.chrome);
const savedVisualizationsLoader = createSavedVisLoader({
savedObjectsClient: core.savedObjects.client,
indexPatterns: data.indexPatterns,
@@ -155,8 +163,9 @@ export class VisualizationsPlugin
* @param {IIndexPattern} indexPattern - index pattern to use
* @param {VisState} visState - visualization configuration
*/
- createVis: (indexPattern: IIndexPattern, visState?: VisState) =>
- new VisImpl(indexPattern, visState),
+ createVis: (visType: string, visState?: SerializedVis) => new Vis(visType, visState),
+ convertToSerializedVis,
+ convertFromSerializedVis,
savedVisualizationsLoader,
};
}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts
index e381a01edef8b..c9906428ccb31 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/_saved_vis.ts
@@ -32,65 +32,74 @@ import {
// @ts-ignore
import { updateOldState } from '../legacy/vis_update_state';
import { extractReferences, injectReferences } from './saved_visualization_references';
-import { IIndexPattern } from '../../../../../../../plugins/data/public';
-import { VisSavedObject } from '../types';
-import { VisImpl } from '../vis_impl';
+import {
+ IIndexPattern,
+ ISearchSource,
+ SearchSource,
+} from '../../../../../../../plugins/data/public';
+import { ISavedVis, SerializedVis } from '../types';
import { createSavedSearchesLoader } from '../../../../../../../plugins/discover/public';
-
-async function _afterEsResp(savedVis: VisSavedObject, services: any) {
- await _getLinkedSavedSearch(savedVis, services);
- savedVis.searchSource!.setField('size', 0);
- savedVis.vis = savedVis.vis ? _updateVis(savedVis) : await _createVis(savedVis);
- return savedVis;
-}
-
-async function _getLinkedSavedSearch(savedVis: VisSavedObject, services: any) {
- const linkedSearch = !!savedVis.savedSearchId;
- const current = savedVis.savedSearch;
-
- if (linkedSearch && current && current.id === savedVis.savedSearchId) {
- return;
- }
-
- if (savedVis.savedSearch) {
- savedVis.searchSource!.setParent(savedVis.savedSearch.searchSource.getParent());
- savedVis.savedSearch.destroy();
- delete savedVis.savedSearch;
- }
- const savedSearches = createSavedSearchesLoader(services);
-
- if (linkedSearch) {
- savedVis.savedSearch = await savedSearches.get(savedVis.savedSearchId!);
- savedVis.searchSource!.setParent(savedVis.savedSearch!.searchSource);
- }
-}
-
-async function _createVis(savedVis: VisSavedObject) {
- savedVis.visState = updateOldState(savedVis.visState);
-
- // visState doesn't yet exist when importing a visualization, so we can't
- // assume that exists at this point. If it does exist, then we're not
- // importing a visualization, so we want to sync the title.
- if (savedVis.visState) {
- savedVis.visState.title = savedVis.title;
- }
-
- savedVis.vis = new VisImpl(savedVis.searchSource!.getField('index')!, savedVis.visState);
-
- savedVis.vis!.savedSearchId = savedVis.savedSearchId;
-
- return savedVis.vis;
-}
-
-function _updateVis(savedVis: VisSavedObject) {
- if (savedVis.vis && savedVis.searchSource) {
- savedVis.vis.indexPattern = savedVis.searchSource.getField('index');
- savedVis.visState.title = savedVis.title;
- savedVis.vis.setState(savedVis.visState);
- savedVis.vis.savedSearchId = savedVis.savedSearchId;
+import { getChrome, getOverlays, getIndexPatterns, getSavedObjects } from '../services';
+
+export const convertToSerializedVis = async (savedVis: ISavedVis): Promise => {
+ const { visState } = savedVis;
+ const searchSource =
+ savedVis.searchSource && (await getSearchSource(savedVis.searchSource, savedVis.savedSearchId));
+
+ const indexPattern =
+ searchSource && searchSource.getField('index') ? searchSource.getField('index')!.id : undefined;
+
+ const aggs = indexPattern ? visState.aggs || [] : visState.aggs;
+
+ return {
+ id: savedVis.id,
+ title: savedVis.title,
+ type: visState.type,
+ description: savedVis.description,
+ params: visState.params,
+ uiState: JSON.parse(savedVis.uiStateJSON || '{}'),
+ data: {
+ indexPattern,
+ aggs,
+ searchSource,
+ savedSearchId: savedVis.savedSearchId,
+ },
+ };
+};
+
+export const convertFromSerializedVis = (vis: SerializedVis): ISavedVis => {
+ return {
+ id: vis.id,
+ title: vis.title,
+ description: vis.description,
+ visState: {
+ type: vis.type,
+ aggs: vis.data.aggs,
+ params: vis.params,
+ },
+ uiStateJSON: JSON.stringify(vis.uiState),
+ searchSource: vis.data.searchSource!,
+ savedSearchId: vis.data.savedSearchId,
+ };
+};
+
+const getSearchSource = async (inputSearchSource: ISearchSource, savedSearchId?: string) => {
+ const searchSource = inputSearchSource.createCopy
+ ? inputSearchSource.createCopy()
+ : new SearchSource({ ...(inputSearchSource as any).fields });
+ if (savedSearchId) {
+ const savedSearch = await createSavedSearchesLoader({
+ savedObjectsClient: getSavedObjects().client,
+ indexPatterns: getIndexPatterns(),
+ chrome: getChrome(),
+ overlays: getOverlays(),
+ }).get(savedSearchId);
+
+ searchSource.setParent(savedSearch.searchSource);
}
- return savedVis.vis;
-}
+ searchSource!.setField('size', 0);
+ return searchSource;
+};
export function createSavedVisClass(services: SavedObjectKibanaServices) {
const SavedObjectClass = createSavedObjectClass(services);
@@ -131,8 +140,16 @@ export function createSavedVisClass(services: SavedObjectKibanaServices) {
savedSearchId: opts.savedSearchId,
version: 1,
},
- afterESResp: (savedObject: SavedObject) => {
- return _afterEsResp(savedObject as VisSavedObject, services) as Promise;
+ afterESResp: async (savedObject: SavedObject) => {
+ const savedVis = (savedObject as any) as ISavedVis;
+ savedVis.visState = await updateOldState(savedVis.visState);
+ if (savedVis.savedSearchId && savedVis.searchSource) {
+ savedObject.searchSource = await getSearchSource(
+ savedVis.searchSource,
+ savedVis.savedSearchId
+ );
+ }
+ return (savedVis as any) as SavedObject;
},
});
this.showInRecentlyAccessed = true;
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.test.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.test.ts
index 98af6d99025c2..2e3a4f0f58b27 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.test.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/saved_visualizations/saved_visualization_references.test.ts
@@ -18,7 +18,7 @@
*/
import { extractReferences, injectReferences } from './saved_visualization_references';
-import { VisSavedObject, VisState } from '../types';
+import { VisSavedObject, SavedVisState } from '../types';
describe('extractReferences', () => {
test('extracts nothing if savedSearchId is empty', () => {
@@ -140,7 +140,7 @@ Object {
},
],
},
- } as unknown) as VisState,
+ } as unknown) as SavedVisState,
} as VisSavedObject;
const references = [
{
@@ -201,7 +201,7 @@ Object {
},
],
},
- } as unknown) as VisState,
+ } as unknown) as SavedVisState,
} as VisSavedObject;
expect(() => injectReferences(context, [])).toThrowErrorMatchingInlineSnapshot(
`"Could not find index pattern reference \\"control_0_index_pattern\\""`
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts
index b2eebe8b5b57d..23cdeae7d15ff 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/services.ts
@@ -18,10 +18,13 @@
*/
import {
+ ApplicationStart,
Capabilities,
+ ChromeStart,
HttpStart,
I18nStart,
IUiSettingsClient,
+ OverlayStart,
SavedObjectsStart,
} from '../../../../../../core/public';
import { TypesStart } from './vis_types';
@@ -76,3 +79,9 @@ export const [getSavedVisualizationsLoader, setSavedVisualizationsLoader] = crea
export const [getAggs, setAggs] = createGetterSetter(
'AggConfigs'
);
+
+export const [getOverlays, setOverlays] = createGetterSetter('Overlays');
+
+export const [getChrome, setChrome] = createGetterSetter('Chrome');
+
+export const [getApplication, setApplication] = createGetterSetter('Application');
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts
index d8e3ccdeb065e..8f93a179af3bc 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/types.ts
@@ -18,21 +18,33 @@
*/
import { SavedObject } from '../../../../../../plugins/saved_objects/public';
-import { Vis, VisState, VisParams, VisualizationController } from './vis';
-import { ISearchSource } from '../../../../../../plugins/data/public/';
-import { SavedSearch } from '../../../../../../plugins/discover/public';
+import { ISearchSource, AggConfigOptions } from '../../../../../../plugins/data/public';
+import { SerializedVis, Vis, VisParams } from './vis';
-export { Vis, VisState, VisParams, VisualizationController };
+export { Vis, SerializedVis, VisParams };
-export interface VisSavedObject extends SavedObject {
- vis: Vis;
- description?: string;
- searchSource: ISearchSource;
+export interface VisualizationController {
+ render(visData: any, visParams: any): Promise;
+ destroy(): void;
+ isLoaded?(): Promise | void;
+}
+
+export interface SavedVisState {
+ type: string;
+ params: VisParams;
+ aggs: AggConfigOptions[];
+}
+
+export interface ISavedVis {
+ id: string;
title: string;
+ description?: string;
+ visState: SavedVisState;
+ searchSource?: ISearchSource;
uiStateJSON?: string;
- destroy: () => void;
savedSearchRefName?: string;
savedSearchId?: string;
- savedSearch?: SavedSearch;
- visState: VisState;
}
+
+// @ts-ignore-next-line
+export interface VisSavedObject extends SavedObject, ISavedVis {}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts
index eb262966a4a22..0ba936c9f6567 100644
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts
+++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts
@@ -17,47 +17,182 @@
* under the License.
*/
+/**
+ * @name Vis
+ *
+ * @description This class consists of aggs, params, listeners, title, and type.
+ * - Aggs: Instances of IAggConfig.
+ * - Params: The settings in the Options tab.
+ *
+ * Not to be confused with vislib/vis.js.
+ */
+
+import { isFunction, defaults, cloneDeep } from 'lodash';
+import { PersistedState } from '../../../../../../../src/plugins/visualizations/public';
+// @ts-ignore
+import { updateVisualizationConfig } from './legacy/vis_update';
+import { getTypes, getAggs } from './services';
import { VisType } from './vis_types';
-import { Status } from './legacy/update_status';
-import { IAggConfigs } from '../../../../../../plugins/data/public';
-
-export interface Vis {
- type: VisType;
- getCurrentState: (
- includeDisabled?: boolean
- ) => {
- title: string;
- type: string;
- params: VisParams;
- aggs: Array<{ [key: string]: any }>;
- };
-
- /**
- * If a visualization based on the saved search,
- * the id is necessary for building an expression function in src/plugins/expressions/common/expression_functions/specs/kibana_context.ts
- */
+import {
+ IAggConfigs,
+ IndexPattern,
+ ISearchSource,
+ AggConfigOptions,
+} from '../../../../../../plugins/data/public';
+
+export interface SerializedVisData {
+ expression?: string;
+ aggs: AggConfigOptions[];
+ indexPattern?: string;
+ searchSource?: ISearchSource;
savedSearchId?: string;
+}
- // Since we haven't typed everything here yet, we basically "any" the rest
- // of that interface. This should be removed as soon as this type definition
- // has been completed. But that way we at least have typing for a couple of
- // properties on that type.
- [key: string]: any;
+export interface SerializedVis {
+ id: string;
+ title: string;
+ description?: string;
+ type: string;
+ params: VisParams;
+ uiState?: any;
+ data: SerializedVisData;
+}
+
+export interface VisData {
+ ast?: string;
+ aggs?: IAggConfigs;
+ indexPattern?: IndexPattern;
+ searchSource?: ISearchSource;
+ savedSearchId?: string;
}
export interface VisParams {
[key: string]: any;
}
-export interface VisState {
- title: string;
- type: VisType;
- params: VisParams;
- aggs: IAggConfigs;
-}
+export class Vis {
+ public readonly type: VisType;
+ public readonly id: string;
+ public title: string = '';
+ public description: string = '';
+ public params: VisParams = {};
+ // Session state is for storing information that is transitory, and will not be saved with the visualization.
+ // For instance, map bounds, which depends on the view port, browser window size, etc.
+ public sessionState: Record = {};
+ public data: VisData = {};
+
+ public readonly uiState: PersistedState;
+
+ constructor(visType: string, visState: SerializedVis = {} as any) {
+ this.type = this.getType(visType);
+ this.params = this.getParams(visState.params);
+ this.uiState = new PersistedState(visState.uiState);
+ this.id = visState.id;
+
+ this.setState(visState || {});
+ }
+
+ private getType(visType: string) {
+ const type = getTypes().get(visType);
+ if (!type) {
+ throw new Error(`Invalid type "${visType}"`);
+ }
+ return type;
+ }
+
+ private getParams(params: VisParams) {
+ return defaults({}, cloneDeep(params || {}), cloneDeep(this.type.visConfig.defaults || {}));
+ }
+
+ setState(state: SerializedVis) {
+ let typeChanged = false;
+ if (state.type && this.type.name !== state.type) {
+ // @ts-ignore
+ this.type = this.getType(state.type);
+ typeChanged = true;
+ }
+ if (state.title !== undefined) {
+ this.title = state.title;
+ }
+ if (state.description !== undefined) {
+ this.description = state.description;
+ }
+ if (state.params || typeChanged) {
+ this.params = this.getParams(state.params);
+ }
+
+ // move to migration script
+ updateVisualizationConfig(state.params, this.params);
+
+ if (state.data && state.data.searchSource) {
+ this.data.searchSource = state.data.searchSource!;
+ this.data.indexPattern = this.data.searchSource.getField('index');
+ }
+ if (state.data && state.data.savedSearchId) {
+ this.data.savedSearchId = state.data.savedSearchId;
+ }
+ if (state.data && state.data.aggs) {
+ let configStates = state.data.aggs;
+ configStates = this.initializeDefaultsFromSchemas(configStates, this.type.schemas.all || []);
+ if (!this.data.indexPattern) {
+ if (state.data.aggs.length) {
+ throw new Error('trying to initialize aggs without index pattern');
+ }
+ return;
+ }
+ this.data.aggs = getAggs().createAggConfigs(this.data.indexPattern, configStates);
+ }
+ }
+
+ clone() {
+ return new Vis(this.type.name, this.serialize());
+ }
+
+ serialize(): SerializedVis {
+ const aggs = this.data.aggs ? this.data.aggs.aggs.map(agg => agg.toJSON()) : [];
+ const indexPattern = this.data.searchSource && this.data.searchSource.getField('index');
+ return {
+ id: this.id,
+ title: this.title,
+ type: this.type.name,
+ params: cloneDeep(this.params) as any,
+ uiState: this.uiState.toJSON(),
+ data: {
+ aggs: aggs as any,
+ indexPattern: indexPattern ? indexPattern.id : undefined,
+ searchSource: this.data.searchSource!.createCopy(),
+ savedSearchId: this.data.savedSearchId,
+ },
+ };
+ }
+
+ toAST() {
+ return this.type.toAST(this.params);
+ }
+
+ // deprecated
+ isHierarchical() {
+ if (isFunction(this.type.hierarchicalData)) {
+ return !!this.type.hierarchicalData(this);
+ } else {
+ return !!this.type.hierarchicalData;
+ }
+ }
-export interface VisualizationController {
- render(visData: any, visParams: any, update: { [key in Status]: boolean }): Promise;
- destroy(): void;
- isLoaded?(): Promise | void;
+ private initializeDefaultsFromSchemas(configStates: AggConfigOptions[], schemas: any) {
+ // Set the defaults for any schema which has them. If the defaults
+ // for some reason has more then the max only set the max number
+ // of defaults (not sure why a someone define more...
+ // but whatever). Also if a schema.name is already set then don't
+ // set anything.
+ const newConfigs = [...configStates];
+ schemas
+ .filter((schema: any) => Array.isArray(schema.defaults) && schema.defaults.length > 0)
+ .filter((schema: any) => !configStates.find(agg => agg.schema && agg.schema === schema.name))
+ .forEach((schema: any) => {
+ const defaultSchemaConfig = schema.defaults.slice(0, schema.max);
+ defaultSchemaConfig.forEach((d: any) => newConfigs.push(d));
+ });
+ return newConfigs;
+ }
}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts
deleted file mode 100644
index 0e759c3d9872c..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.d.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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 { Vis, VisState, VisParams } from './vis';
-import { VisType } from './vis_types';
-import { IAggConfig, IIndexPattern } from '../../../../../../plugins/data/public';
-import { Schema } from '../../../../vis_default_editor/public';
-
-type InitVisStateType =
- | Partial
- | Partial & { type: string }>
- | string;
-
-export type VisImplConstructor = new (
- indexPattern: IIndexPattern,
- visState?: InitVisStateType
-) => VisImpl;
-
-export declare class VisImpl implements Vis {
- constructor(indexPattern: IIndexPattern, visState?: InitVisStateType);
-
- type: VisType;
- getCurrentState: (
- includeDisabled?: boolean
- ) => {
- title: string;
- type: string;
- params: VisParams;
- aggs: Array<{ [key: string]: any }>;
- };
-
- private initializeDefaultsFromSchemas(configStates: IAggConfig[], schemas: Schema[]);
-
- // Since we haven't typed everything here yet, we basically "any" the rest
- // of that interface. This should be removed as soon as this type definition
- // has been completed. But that way we at least have typing for a couple of
- // properties on that type.
- [key: string]: any;
-}
diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js
deleted file mode 100644
index abd8f351ae94d..0000000000000
--- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis_impl.js
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * @name Vis
- *
- * @description This class consists of aggs, params, listeners, title, and type.
- * - Aggs: Instances of IAggConfig.
- * - Params: The settings in the Options tab.
- *
- * Not to be confused with vislib/vis.js.
- */
-
-import { EventEmitter } from 'events';
-import _ from 'lodash';
-import { PersistedState } from '../../../../../../../src/plugins/visualizations/public';
-import { updateVisualizationConfig } from './legacy/vis_update';
-import { getTypes, getAggs } from './services';
-
-class VisImpl extends EventEmitter {
- constructor(indexPattern, visState) {
- super();
- visState = visState || {};
-
- if (_.isString(visState)) {
- visState = {
- type: visState,
- };
- }
-
- this.indexPattern = indexPattern;
- this._setUiState(new PersistedState());
- this.setCurrentState(visState);
- this.setState(this.getCurrentState(), false);
-
- // Session state is for storing information that is transitory, and will not be saved with the visualization.
- // For instance, map bounds, which depends on the view port, browser window size, etc.
- this.sessionState = {};
-
- this.API = {
- events: {
- filter: data => this.eventsSubject.next({ name: 'filterBucket', data }),
- brush: data => this.eventsSubject.next({ name: 'brush', data }),
- },
- };
- }
-
- initializeDefaultsFromSchemas(configStates, schemas) {
- // Set the defaults for any schema which has them. If the defaults
- // for some reason has more then the max only set the max number
- // of defaults (not sure why a someone define more...
- // but whatever). Also if a schema.name is already set then don't
- // set anything.
- const newConfigs = [...configStates];
- schemas
- .filter(schema => Array.isArray(schema.defaults) && schema.defaults.length > 0)
- .filter(schema => !configStates.find(agg => agg.schema && agg.schema === schema.name))
- .forEach(schema => {
- const defaults = schema.defaults.slice(0, schema.max);
- defaults.forEach(d => newConfigs.push(d));
- });
- return newConfigs;
- }
-
- setCurrentState(state) {
- this.title = state.title || '';
- const type = state.type || this.type;
- if (_.isString(type)) {
- this.type = getTypes().get(type);
- if (!this.type) {
- throw new Error(`Invalid type "${type}"`);
- }
- } else {
- this.type = type;
- }
-
- this.params = _.defaults(
- {},
- _.cloneDeep(state.params || {}),
- _.cloneDeep(this.type.visConfig.defaults || {})
- );
-
- updateVisualizationConfig(state.params, this.params);
-
- if (state.aggs || !this.aggs) {
- let configStates = state.aggs ? state.aggs.aggs || state.aggs : [];
- configStates = this.initializeDefaultsFromSchemas(configStates, this.type.schemas.all || []);
- this.aggs = getAggs().createAggConfigs(this.indexPattern, configStates);
- }
- }
-
- setState(state, updateCurrentState = true) {
- this._state = _.cloneDeep(state);
- if (updateCurrentState) {
- this.setCurrentState(this._state);
- }
- }
-
- setVisType(type) {
- this.type.type = type;
- }
-
- updateState() {
- this.setState(this.getCurrentState(true));
- this.emit('update');
- }
-
- forceReload() {
- this.emit('reload');
- }
-
- getCurrentState(includeDisabled) {
- return {
- title: this.title,
- type: this.type.name,
- params: _.cloneDeep(this.params),
- aggs: this.aggs.aggs
- .map(agg => agg.toJSON())
- .filter(agg => includeDisabled || agg.enabled)
- .filter(Boolean),
- };
- }
-
- copyCurrentState(includeDisabled = false) {
- const state = this.getCurrentState(includeDisabled);
- state.aggs = getAggs().createAggConfigs(
- this.indexPattern,
- state.aggs.aggs || state.aggs,
- this.type.schemas.all
- );
- return state;
- }
-
- getStateInternal(includeDisabled) {
- return {
- title: this._state.title,
- type: this._state.type,
- params: this._state.params,
- aggs: this._state.aggs.filter(agg => includeDisabled || agg.enabled),
- };
- }
-
- getEnabledState() {
- return this.getStateInternal(false);
- }
-
- getAggConfig() {
- return this.aggs.clone({ enabledOnly: true });
- }
-
- getState() {
- return this.getStateInternal(true);
- }
-
- isHierarchical() {
- if (_.isFunction(this.type.hierarchicalData)) {
- return !!this.type.hierarchicalData(this);
- } else {
- return !!this.type.hierarchicalData;
- }
- }
-
- hasSchemaAgg(schemaName, aggTypeName) {
- const aggs = this.aggs.bySchemaName(schemaName) || [];
- return aggs.some(function(agg) {
- if (!agg.type || !agg.type.name) return false;
- return agg.type.name === aggTypeName;
- });
- }
-
- hasUiState() {
- return !!this.__uiState;
- }
-
- /***
- * this should not be used outside of visualize
- * @param uiState
- * @private
- */
- _setUiState(uiState) {
- if (uiState instanceof PersistedState) {
- this.__uiState = uiState;
- }
- }
-
- getUiState() {
- return this.__uiState;
- }
-
- /**
- * Currently this is only used to extract map-specific information
- * (e.g. mapZoom, mapCenter).
- */
- uiStateVal(key, val) {
- if (this.hasUiState()) {
- if (_.isUndefined(val)) {
- return this.__uiState.get(key);
- }
- return this.__uiState.set(key, val);
- }
- return val;
- }
-}
-
-VisImpl.prototype.type = 'histogram';
-
-export { VisImpl };
diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts
index 339a5fea91c5f..977b9568ceaa6 100644
--- a/src/plugins/data/public/index.ts
+++ b/src/plugins/data/public/index.ts
@@ -328,6 +328,7 @@ export {
AggParamType,
AggTypeFieldFilters, // TODO convert to interface
AggTypeFilters, // TODO convert to interface
+ AggConfigOptions,
BUCKET_TYPES,
DateRangeKey, // only used in field formatter deserialization, which will live in data
IAggConfig,
diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md
index 848044217767e..87d2cffc0ab33 100644
--- a/src/plugins/data/public/public.api.md
+++ b/src/plugins/data/public/public.api.md
@@ -54,6 +54,22 @@ import { Unit } from '@elastic/datemath';
import { UnregisterCallback } from 'history';
import { UserProvidedValues } from 'src/core/server/types';
+// Warning: (ae-missing-release-tag) "AggConfigOptions" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
+//
+// @public (undocumented)
+export interface AggConfigOptions {
+ // (undocumented)
+ enabled?: boolean;
+ // (undocumented)
+ id?: string;
+ // (undocumented)
+ params?: Record;
+ // (undocumented)
+ schema?: string;
+ // (undocumented)
+ type: IAggType;
+}
+
// Warning: (ae-missing-release-tag) "AggGroupNames" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
@@ -1838,21 +1854,21 @@ export type TSearchStrategyProvider = (context: ISearc
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "getRoutes" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:379:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:379:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:379:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:379:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:384:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:385:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:387:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:396:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
-// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:380:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:385:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:386:1 - (ae-forgotten-export) The symbol "convertDateRangeToString" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:388:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:397:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:398:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:402:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:403:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
+// src/plugins/data/public/index.ts:410: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:33:33 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:37:1 - (ae-forgotten-export) The symbol "QueryStateChange" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/types.ts:52:5 - (ae-forgotten-export) The symbol "createFiltersFromEvent" needs to be exported by the entry point index.d.ts
diff --git a/src/plugins/visualizations/public/persisted_state/persisted_state.ts b/src/plugins/visualizations/public/persisted_state/persisted_state.ts
index b81b651c73509..3e675574fd678 100644
--- a/src/plugins/visualizations/public/persisted_state/persisted_state.ts
+++ b/src/plugins/visualizations/public/persisted_state/persisted_state.ts
@@ -85,7 +85,7 @@ export class PersistedState extends EventEmitter {
setSilent(key: PersistedStateKey | any, value?: any) {
const params = prepSetParams(key, value, this._path);
- if (params.key) {
+ if (params.key || params.value) {
return this.setValue(params.key, params.value, true);
}
}