Skip to content

Commit

Permalink
Adds embeddable objects to canvas
Browse files Browse the repository at this point in the history
  • Loading branch information
Corey Robertson committed Aug 2, 2019
1 parent dd75d83 commit 740454a
Show file tree
Hide file tree
Showing 28 changed files with 837 additions and 10 deletions.
1 change: 1 addition & 0 deletions x-pack/dev-tools/jest/create_jest_config.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ export function createJestConfig({
],
transform: {
'^.+\\.(js|tsx?)$': `${kibanaDirectory}/src/dev/jest/babel_transform.js`,
'^.+\\.html?$': 'jest-raw-loader',
},
transformIgnorePatterns: [
// ignore all node_modules except @elastic/eui which requires babel transforms to handle dynamic import()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ExpressionType } from '../../../../../../src/plugins/data/common/expressions';
// @ts-ignore Untyped Local
import { MAP_SAVED_OBJECT_TYPE } from '../../../maps/common/constants';
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/embeddable/search_embeddable';
// TODO: Doing this visualize import makes type_check fail
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable';
import { EmbeddableInput } from '../../../../../../src/legacy/core_plugins/embeddable_api/public';

export const EmbeddableExpressionType = 'embeddable';

export const EmbeddableTypes = {
map: MAP_SAVED_OBJECT_TYPE,
search: SEARCH_EMBEDDABLE_TYPE,
visualization: VISUALIZE_EMBEDDABLE_TYPE,
};

export interface EmbeddableExpression<Input extends EmbeddableInput> {
type: typeof EmbeddableExpressionType;
input: Input;
embeddableType: string;
}

export const embeddableType = (): ExpressionType<
typeof EmbeddableExpressionType,
EmbeddableExpression<any>
> => ({
name: EmbeddableExpressionType,
to: {
render: (embeddableExpression: EmbeddableExpression<any>) => {
return {
type: 'render',
as: EmbeddableExpressionType,
value: embeddableExpression,
};
},
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { embeddableType } from './embeddable';

export * from './embeddable';

export const typeFunctions = [embeddableType];
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ import { rounddate } from './rounddate';
import { rowCount } from './rowCount';
import { repeatImage } from './repeatImage';
import { revealImage } from './revealImage';
import { savedMap } from './savedMap';
import { savedSearch } from './savedSearch';
import { savedVisualization } from './savedVisualization';
import { seriesStyle } from './seriesStyle';
import { shape } from './shape';
import { sort } from './sort';
Expand Down Expand Up @@ -103,6 +106,9 @@ export const functions = [
revealImage,
rounddate,
rowCount,
savedMap,
savedSearch,
savedVisualization,
seriesStyle,
shape,
sort,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { savedMap } from './savedMap';
import { buildEmbeddableFilters } from '../../../server/lib/build_embeddable_filters';

const filterContext = {
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
and: [],
column: 'time-column',
type: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},
],
};

describe('savedMap', () => {
const fn = savedMap().fn;
const args = {
id: 'some-id',
};

it('accepts null context', () => {
const expression = fn(null, args, {});

expect(expression.input.filters).toEqual([]);
expect(expression.input.timeRange).toBeUndefined();
});

it('accepts filter context', () => {
const expression = fn(filterContext, args, {});
const embeddableFilters = buildEmbeddableFilters(filterContext.and);

expect(expression.input.filters).toEqual(embeddableFilters.filters);
expect(expression.input.timeRange).toEqual(embeddableFilters.timeRange);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { Filter as ESFilterType } from '@kbn/es-query';
import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
import { TimeRange } from 'ui/timefilter/time_history';
import { EmbeddableInput } from '../../../../../../../src/legacy/core_plugins/embeddable_api/public';
import { buildEmbeddableFilters } from '../../../server/lib/build_embeddable_filters';
import { Filter } from '../../../types';
import {
EmbeddableTypes,
EmbeddableExpressionType,
EmbeddableExpression,
} from '../../expression_types';

interface Arguments {
id: string;
}

// Map embeddable is missing proper typings, so type is just to document what we
// are expecting to pass to the embeddable
interface SavedMapInput extends EmbeddableInput {
id: string;
timeRange?: TimeRange;
refreshConfig: {
isPaused: boolean;
interval: number;
};
filters: ESFilterType[];
}

type Return = EmbeddableExpression<SavedMapInput>;

export function savedMap(): ExpressionFunction<'savedMap', Filter | null, Arguments, Return> {
return {
name: 'savedMap',
help: 'Render a Saved Map',
args: {
id: {
types: ['string'],
required: false,
help: 'Id of the saved map',
},
},
type: EmbeddableExpressionType,
fn: (context, { id }) => {
const filters = context ? context.and : [];

return {
type: EmbeddableExpressionType,
input: {
id,
...buildEmbeddableFilters(filters),

refreshConfig: {
isPaused: false,
interval: 0,
},
},
embeddableType: EmbeddableTypes.map,
};
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { savedSearch } from './savedSearch';
import { buildEmbeddableFilters } from '../../../server/lib/build_embeddable_filters';

const filterContext = {
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
and: [],
column: 'time-column',
type: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},
],
};

describe('savedSearch', () => {
const fn = savedSearch().fn;
const args = {
id: 'some-id',
};

it('accepts null context', () => {
const expression = fn(null, args, {});

expect(expression.input.filters).toEqual([]);
expect(expression.input.timeRange).toBeUndefined();
});

it('accepts filter context', () => {
const expression = fn(filterContext, args, {});
const embeddableFilters = buildEmbeddableFilters(filterContext.and);

expect(expression.input.filters).toEqual(embeddableFilters.filters);
expect(expression.input.timeRange).toEqual(embeddableFilters.timeRange);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
import {
EmbeddableTypes,
EmbeddableExpressionType,
EmbeddableExpression,
} from '../../expression_types';

import { SearchInput } from '../../../../../../../src/legacy/core_plugins/kibana/public/discover/embeddable';
import { buildEmbeddableFilters } from '../../../server/lib/build_embeddable_filters';
import { Filter } from '../../../types';

interface Arguments {
id: string;
}

type Return = EmbeddableExpression<Partial<SearchInput> & { id: SearchInput['id'] }>;

export function savedSearch(): ExpressionFunction<'savedSearch', Filter | null, Arguments, Return> {
return {
name: 'savedSearch',
help: 'Render a Saved Search Query',
args: {
id: {
types: ['string'],
required: false,
help: 'Id of the saved search',
},
},
type: EmbeddableExpressionType,
fn: (context, { id }) => {
const filters = context ? context.and : [];
return {
type: EmbeddableExpressionType,
input: {
id,
...buildEmbeddableFilters(filters),
},
embeddableType: EmbeddableTypes.search,
};
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { savedVisualization } from './savedVisualization';
import { buildEmbeddableFilters } from '../../../server/lib/build_embeddable_filters';

const filterContext = {
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
and: [],
column: 'time-column',
type: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},
],
};

describe('savedVisualization', () => {
const fn = savedVisualization().fn;
const args = {
id: 'some-id',
};

it('accepts null context', () => {
const expression = fn(null, args, {});

expect(expression.input.filters).toEqual([]);
expect(expression.input.timeRange).toBeUndefined();
});

it('accepts filter context', () => {
const expression = fn(filterContext, args, {});
const embeddableFilters = buildEmbeddableFilters(filterContext.and);

expect(expression.input.filters).toEqual(embeddableFilters.filters);
expect(expression.input.timeRange).toEqual(embeddableFilters.timeRange);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { ExpressionFunction } from 'src/legacy/core_plugins/interpreter/public';
import {
EmbeddableTypes,
EmbeddableExpressionType,
EmbeddableExpression,
} from '../../expression_types';
// import { VisualizeInput } from '../../../../../../../src/legacy/core_plugins/kibana/public/visualize/embeddable';
import { buildEmbeddableFilters } from '../../../server/lib/build_embeddable_filters';
import { Filter } from '../../../types';

interface Arguments {
id: string;
}

// TODO: Importing from visualize/embeddable chokes type_check script
// Using an any here now until we can get that resolved
type Return = EmbeddableExpression</* VisualizeInput */ any & { id: string }>;

export function savedVisualization(): ExpressionFunction<
'savedVisualization',
Filter | null,
Arguments,
Return
> {
return {
name: 'savedVisualization',
help: 'Render a Saved Search Query',
args: {
id: {
types: ['string'],
required: false,
help: 'Id of the saved search',
},
},
type: EmbeddableExpressionType,
fn: (context, { id }) => {
const filters = context ? context.and : [];

return {
type: EmbeddableExpressionType,
input: {
id,
...buildEmbeddableFilters(filters),
},
embeddableType: EmbeddableTypes.visualization,
};
},
};
}
Loading

0 comments on commit 740454a

Please sign in to comment.