Skip to content

Commit

Permalink
Adds save and return flow to Canvas
Browse files Browse the repository at this point in the history
Updates existing embeddable with updates on edit

Select incoming embeddable element on load

Fixed ts errors

Added use incoming embeddable hook

Fixed eslint errors

Added comment

Fixed typo

Fixed story

Fix ts errors

Fixed failing tests

Fixed ts errors
  • Loading branch information
cqliu1 committed Oct 15, 2021
1 parent 2030a15 commit 55cefdc
Show file tree
Hide file tree
Showing 29 changed files with 373 additions and 79 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ export class EditPanelAction implements Action<ActionContext> {
valueInput: byValueMode ? this.getExplicitInput({ embeddable }) : undefined,
embeddableId: embeddable.id,
searchSessionId: embeddable.getInput().searchSessionId,
originatingPath: window.location.hash,
};
return { app, path, state };
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
*/

import { ExpressionTypeDefinition } from '../../../../../src/plugins/expressions';
import { EmbeddableInput } from '../../../../../src/plugins/embeddable/common/';
import { EmbeddableInput } from '../../types';
import { EmbeddableTypes } from './embeddable_types';

export const EmbeddableExpressionType = 'embeddable';
export { EmbeddableTypes, EmbeddableInput };

export interface EmbeddableExpression<Input extends EmbeddableInput> {
/**
* The type of the expression result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,8 @@
*/

import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { TimeRange } from 'src/plugins/data/public';
import { Filter } from '@kbn/es-query';
import { ExpressionValueFilter } from '../../../types';
import {
EmbeddableExpressionType,
EmbeddableExpression,
EmbeddableInput as Input,
} from '../../expression_types';
import { ExpressionValueFilter, EmbeddableInput } from '../../../types';
import { EmbeddableExpressionType, EmbeddableExpression } from '../../expression_types';
import { getFunctionHelp } from '../../../i18n';
import { SavedObjectReference } from '../../../../../../src/core/types';
import { getQueryFilters } from '../../../common/lib/build_embeddable_filters';
Expand All @@ -29,12 +23,6 @@ const defaultTimeRange = {
to: 'now',
};

export type EmbeddableInput = Input & {
timeRange?: TimeRange;
filters?: Filter[];
savedObjectId: string;
};

const baseEmbeddableInput = {
timeRange: defaultTimeRange,
disableTriggers: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,8 @@ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { PaletteOutput } from 'src/plugins/charts/common';
import { Filter as DataFilter } from '@kbn/es-query';
import { TimeRange } from 'src/plugins/data/common';
import { EmbeddableInput } from 'src/plugins/embeddable/common';
import { getQueryFilters } from '../../../common/lib/build_embeddable_filters';
import { ExpressionValueFilter, TimeRange as TimeRangeArg } from '../../../types';
import { ExpressionValueFilter, EmbeddableInput, TimeRange as TimeRangeArg } from '../../../types';
import {
EmbeddableTypes,
EmbeddableExpressionType,
Expand All @@ -27,7 +26,7 @@ interface Arguments {
}

export type SavedLensInput = EmbeddableInput & {
id: string;
savedObjectId: string;
timeRange?: TimeRange;
filters: DataFilter[];
palette?: PaletteOutput;
Expand Down Expand Up @@ -73,18 +72,19 @@ export function savedLens(): ExpressionFunctionDefinition<
},
},
type: EmbeddableExpressionType,
fn: (input, args) => {
fn: (input, { id, timerange, title, palette }) => {
const filters = input ? input.and : [];

return {
type: EmbeddableExpressionType,
input: {
id: args.id,
id,
savedObjectId: id,
filters: getQueryFilters(filters),
timeRange: args.timerange || defaultTimeRange,
title: args.title === null ? undefined : args.title,
timeRange: timerange || defaultTimeRange,
title: title === null ? undefined : title,
disableTriggers: true,
palette: args.palette,
palette,
},
embeddableType: EmbeddableTypes.lens,
generatedAt: Date.now(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const defaultTimeRange = {
to: 'now',
};

type Output = EmbeddableExpression<MapEmbeddableInput>;
type Output = EmbeddableExpression<MapEmbeddableInput & { savedObjectId: string }>;

export function savedMap(): ExpressionFunctionDefinition<
'savedMap',
Expand Down Expand Up @@ -85,8 +85,9 @@ export function savedMap(): ExpressionFunctionDefinition<
return {
type: EmbeddableExpressionType,
input: {
attributes: { title: '' },
id: args.id,
attributes: { title: '' },
savedObjectId: args.id,
filters: getQueryFilters(filters),
timeRange: args.timerange || defaultTimeRange,
refreshConfig: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ interface Arguments {
title: string | null;
}

type Output = EmbeddableExpression<VisualizeInput>;
type Output = EmbeddableExpression<VisualizeInput & { savedObjectId: string }>;

const defaultTimeRange = {
from: 'now-15m',
Expand Down Expand Up @@ -94,6 +94,7 @@ export function savedVisualization(): ExpressionFunctionDefinition<
type: EmbeddableExpressionType,
input: {
id,
savedObjectId: id,
disableTriggers: true,
timeRange: timerange || defaultTimeRange,
filters: getQueryFilters(filters),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import {
IEmbeddable,
EmbeddableFactory,
EmbeddableFactoryNotFoundError,
isErrorEmbeddable,
} from '../../../../../../src/plugins/embeddable/public';
import { EmbeddableExpression } from '../../expression_types/embeddable';
import { RendererStrings } from '../../../i18n';
import { embeddableInputToExpression } from './embeddable_input_to_expression';
import { EmbeddableInput } from '../../expression_types';
import { RendererFactory } from '../../../types';
import { RendererFactory, EmbeddableInput } from '../../../types';
import { CANVAS_EMBEDDABLE_CLASSNAME } from '../../../common/lib';

const { embeddable: strings } = RendererStrings;
Expand Down Expand Up @@ -71,16 +71,27 @@ export const embeddableRendererFactory = (
throw new EmbeddableFactoryNotFoundError(embeddableType);
}

const embeddablePromise = factory
.createFromSavedObject(input.id, input)
.then((embeddable) => {
// stores embeddable in registrey
embeddablesRegistry[uniqueId] = embeddable;
return embeddable;
});
embeddablesRegistry[uniqueId] = embeddablePromise;

const embeddableObject = await (async () => embeddablePromise)();
const embeddableInput = { ...input, id: uniqueId };

const embeddablePromise = input.savedObjectId
? factory
.createFromSavedObject(input.savedObjectId, embeddableInput)
.then((embeddable) => {
// stores embeddable in registrey
embeddablesRegistry[uniqueId] = embeddable;
return embeddable;
})
: factory.create(embeddableInput).then((embeddable) => {
if (!embeddable || isErrorEmbeddable(embeddable)) {
return;
}
// stores embeddable in registry
embeddablesRegistry[uniqueId] = embeddable as IEmbeddable;
return embeddable;
});
embeddablesRegistry[uniqueId] = embeddablePromise as Promise<IEmbeddable>;

const embeddableObject = (await (async () => embeddablePromise)()) as IEmbeddable;

const palettes = await plugins.charts.palettes.getPalettes();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { toExpression } from './embeddable';
import { EmbeddableInput } from '../../../../types';
import { decode } from '../../../../common/lib/embeddable_dataurl';
import { fromExpression } from '@kbn/interpreter/common';

describe('toExpression', () => {
describe('by-reference embeddable input', () => {
const baseEmbeddableInput = {
id: 'elementId',
savedObjectId: 'embeddableId',
filters: [],
};

it('converts to an embeddable expression', () => {
const input: EmbeddableInput = baseEmbeddableInput;

const expression = toExpression(input, 'visualization');
const ast = fromExpression(expression);

expect(ast.type).toBe('expression');
expect(ast.chain[0].function).toBe('embeddable');
expect(ast.chain[0].arguments.type[0]).toBe('visualization');

const config = decode(ast.chain[0].arguments.config[0] as string);

expect(config.savedObjectId).toStrictEqual(input.savedObjectId);
});

it('includes optional input values', () => {
const input: EmbeddableInput = {
...baseEmbeddableInput,
title: 'title',
timeRange: {
from: 'now-1h',
to: 'now',
},
};

const expression = toExpression(input, 'visualization');
const ast = fromExpression(expression);

const config = decode(ast.chain[0].arguments.config[0] as string);

expect(config).toHaveProperty('title', input.title);
expect(config).toHaveProperty('timeRange');
expect(config.timeRange).toHaveProperty('from', input.timeRange?.from);
expect(config.timeRange).toHaveProperty('to', input.timeRange?.to);
});

it('includes empty panel title', () => {
const input: EmbeddableInput = {
...baseEmbeddableInput,
title: '',
};

const expression = toExpression(input, 'visualization');
const ast = fromExpression(expression);

const config = decode(ast.chain[0].arguments.config[0] as string);

expect(config).toHaveProperty('title', input.title);
});
});

describe('by-value embeddable input', () => {
const baseEmbeddableInput = {
id: 'elementId',
disableTriggers: true,
filters: [],
};
it('converts to an embeddable expression', () => {
const input: EmbeddableInput = baseEmbeddableInput;

const expression = toExpression(input, 'visualization');
const ast = fromExpression(expression);

expect(ast.type).toBe('expression');
expect(ast.chain[0].function).toBe('embeddable');
expect(ast.chain[0].arguments.type[0]).toBe('visualization');

const config = decode(ast.chain[0].arguments.config[0] as string);
expect(config.filters).toStrictEqual(input.filters);
expect(config.disableTriggers).toStrictEqual(input.disableTriggers);
});

it('includes optional input values', () => {
const input: EmbeddableInput = {
...baseEmbeddableInput,
title: 'title',
timeRange: {
from: 'now-1h',
to: 'now',
},
};

const expression = toExpression(input, 'visualization');
const ast = fromExpression(expression);

const config = decode(ast.chain[0].arguments.config[0] as string);

expect(config).toHaveProperty('title', input.title);
expect(config).toHaveProperty('timeRange');
expect(config.timeRange).toHaveProperty('from', input.timeRange?.from);
expect(config.timeRange).toHaveProperty('to', input.timeRange?.to);
});

it('includes empty panel title', () => {
const input: EmbeddableInput = {
...baseEmbeddableInput,
title: '',
};

const expression = toExpression(input, 'visualization');
const ast = fromExpression(expression);

const config = decode(ast.chain[0].arguments.config[0] as string);

expect(config).toHaveProperty('title', input.title);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import { fromExpression, Ast } from '@kbn/interpreter/common';
import { chartPluginMock } from 'src/plugins/charts/public/mocks';

const baseEmbeddableInput = {
id: 'embeddableId',
id: 'elementId',
savedObjectId: 'embeddableId',
filters: [],
};

Expand All @@ -27,7 +28,7 @@ describe('toExpression', () => {
expect(ast.type).toBe('expression');
expect(ast.chain[0].function).toBe('savedLens');

expect(ast.chain[0].arguments.id).toStrictEqual([input.id]);
expect(ast.chain[0].arguments.id).toStrictEqual([input.savedObjectId]);

expect(ast.chain[0].arguments).not.toHaveProperty('title');
expect(ast.chain[0].arguments).not.toHaveProperty('timerange');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function toExpression(input: SavedLensInput, palettes: PaletteRegistry):

expressionParts.push('savedLens');

expressionParts.push(`id="${input.id}"`);
expressionParts.push(`id="${input.savedObjectId}"`);

if (input.title !== undefined) {
expressionParts.push(`title="${input.title}"`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
*/

import { toExpression } from './map';
import { MapEmbeddableInput } from '../../../../../../plugins/maps/public/embeddable';
import { fromExpression, Ast } from '@kbn/interpreter/common';

const baseSavedMapInput = {
id: 'elementId',
attributes: { title: '' },
id: 'embeddableId',
savedObjectId: 'embeddableId',
filters: [],
isLayerTOCOpen: false,
refreshConfig: {
Expand All @@ -23,7 +23,7 @@ const baseSavedMapInput = {

describe('toExpression', () => {
it('converts to a savedMap expression', () => {
const input: MapEmbeddableInput = {
const input = {
...baseSavedMapInput,
};

Expand All @@ -33,15 +33,15 @@ describe('toExpression', () => {
expect(ast.type).toBe('expression');
expect(ast.chain[0].function).toBe('savedMap');

expect(ast.chain[0].arguments.id).toStrictEqual([input.id]);
expect(ast.chain[0].arguments.id).toStrictEqual([input.savedObjectId]);

expect(ast.chain[0].arguments).not.toHaveProperty('title');
expect(ast.chain[0].arguments).not.toHaveProperty('center');
expect(ast.chain[0].arguments).not.toHaveProperty('timerange');
});

it('includes optional input values', () => {
const input: MapEmbeddableInput = {
const input = {
...baseSavedMapInput,
mapCenter: {
lat: 1,
Expand Down Expand Up @@ -73,7 +73,7 @@ describe('toExpression', () => {
});

it('includes empty panel title', () => {
const input: MapEmbeddableInput = {
const input = {
...baseSavedMapInput,
title: '',
};
Expand Down
Loading

0 comments on commit 55cefdc

Please sign in to comment.