Skip to content

Commit

Permalink
MISC
Browse files Browse the repository at this point in the history
  • Loading branch information
stacey-gammon committed Apr 26, 2019
1 parent 1484788 commit 1ce9f30
Show file tree
Hide file tree
Showing 38 changed files with 1,019 additions and 658 deletions.

This file was deleted.

1 change: 0 additions & 1 deletion src/legacy/core_plugins/embeddable_api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* under the License.
*/

// @ts-ignore
import { resolve } from 'path';

// eslint-disable-next-line import/no-default-export
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@
* under the License.
*/

import { i18n } from '@kbn/i18n';
import { Container, ContainerInput } from '../containers';
import { EmbeddableInput, Embeddable, EmbeddableOutput } from '../embeddables';
import { Embeddable } from '../embeddables';
import { APPLY_FILTER_TRIGGER, triggerRegistry } from '../triggers';
import { Filter } from '../types';
import { Action } from './action';
import { actionRegistry } from './action_registry';
import { IncompatibleActionError } from './incompatible_action_error';

interface ApplyFilterContainerInput extends ContainerInput {
filters: Filter[];
Expand All @@ -31,29 +33,24 @@ interface ApplyFilterContainerInput extends ContainerInput {
const APPLY_FILTER_ACTION_ID = 'APPLY_FILTER_ACTION_ID';

function containerAcceptsFilterInput(
container: Embeddable | Container<{ id: string }, {}, ApplyFilterContainerInput>
): container is Container<{ id: string }, {}, ApplyFilterContainerInput> {
return (
(container as Container<{ id: string }, {}, ApplyFilterContainerInput>).getInput().filters !==
undefined
);
container: Embeddable | Container | Container<any, ApplyFilterContainerInput>
): container is Container<any, ApplyFilterContainerInput> {
return (container as Container<any, ApplyFilterContainerInput>).getInput().filters !== undefined;
}

export class ApplyFilterAction extends Action<
Embeddable,
Container<EmbeddableInput, EmbeddableOutput, ApplyFilterContainerInput>,
{ filters: Filter[] }
> {
export class ApplyFilterAction extends Action<Embeddable, Container, { filters: Filter[] }> {
constructor() {
super(APPLY_FILTER_ACTION_ID);
}

public getTitle() {
return 'Apply filter to current view';
return i18n.translate('embeddableApi.actions.applyFilterActionTitle', {
defaultMessage: 'Apply filter to current view',
});
}

public isCompatible(context: { embeddable: Embeddable }) {
let root = context.embeddable;
let root: Embeddable | Container = context.embeddable;
while (root.parent) {
root = root.parent;
}
Expand All @@ -71,15 +68,21 @@ export class ApplyFilterAction extends Action<
if (!triggerContext) {
throw new Error('Applying a filter requires a filter as context');
}
let root = embeddable;
let root: Embeddable | Container = embeddable;
while (root.parent) {
root = root.parent;
}
(root as Container<{ id: string }, {}, ApplyFilterContainerInput>).updateInput({

if (!containerAcceptsFilterInput(root)) {
throw new IncompatibleActionError();
}

root.updateInput({
filters: triggerContext.filters,
});
}
}

const applyFilterAction = new ApplyFilterAction();
if (!actionRegistry.getAction(applyFilterAction.id)) {
actionRegistry.addAction(new ApplyFilterAction());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
* under the License.
*/

import { combineReducers } from 'redux';
import { dashboard } from './dashboard/reducers';
import { CoreKibanaState } from './selectors';
import { i18n } from '@kbn/i18n';

/**
* Only a single reducer now, but eventually there should be one for each sub app that is part of the
* core kibana plugins.
*/
export const reducers = combineReducers<CoreKibanaState>({
dashboard,
});
export class IncompatibleActionError extends Error {
constructor() {
super(
i18n.translate('embeddableApi.errors.incompatibleAction', {
defaultMessage: 'Action is incompatible',
})
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@

export { Action, ActionContext, ExecuteActionContext } from './action';
export { actionRegistry } from './action_registry';
export { IncompatibleActionError } from './incompatible_action_error';
Original file line number Diff line number Diff line change
Expand Up @@ -422,3 +422,73 @@ test('Explicit embeddable input mapped to undefined will default to inherited',
derivedFilter,
]);
});

test('Panel removed from input state', async done => {
const container = new FilterableContainer(
{ id: 'hello', panels: {}, filters: [] },
embeddableFactories
);

const embeddable = await container.addNewEmbeddable<
FilterableEmbeddableInput,
FilterableEmbeddable
>(FILTERABLE_EMBEDDABLE, {});

const newInput = {
...container.getInput(),
panels: {
...container.getInput().panels,
[embeddable.id]: undefined,
},
};

const subscription = container
.getOutput$()
.pipe(skip(1))
.subscribe(() => {
expect(container.getChild(embeddable.id)).toBeUndefined();
expect(container.getOutput().embeddableLoaded[embeddable.id]).toBeUndefined();
subscription.unsubscribe();
done();
});

container.updateInput(newInput);
});

test('Panel added to input state', async done => {
const container = new FilterableContainer(
{ id: 'hello', panels: {}, filters: [] },
embeddableFactories
);

const embeddable = await container.addNewEmbeddable<
FilterableEmbeddableInput,
FilterableEmbeddable
>(FILTERABLE_EMBEDDABLE, {});

const newInput = {
...container.getInput(),
panels: {
...container.getInput().panels,
[embeddable.id]: undefined,
},
};

const container2 = new FilterableContainer(
{ id: 'hello', panels: {}, filters: [] },
embeddableFactories
);

const subscription = container2
.getOutput$()
.pipe(skip(1))
.subscribe(() => {
expect(container.getChild(embeddable.id)).toBeDefined();
expect(container.getOutput().embeddableLoaded[embeddable.id]).toBe(true);
subscription.unsubscribe();
done();
});

// Container 1 has the panel in it's array, copy it to container2.
container2.updateInput(container.getInput());
});
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*/

import uuid from 'uuid';
import { i18n } from '@kbn/i18n';
import { Subscription } from 'rxjs';
import {
Embeddable,
EmbeddableFactoryRegistry,
Expand Down Expand Up @@ -65,6 +67,8 @@ export abstract class Container<
} = {};
public readonly embeddableFactories: EmbeddableFactoryRegistry;

private subscription: Subscription;

constructor(
type: string,
input: I,
Expand All @@ -75,14 +79,19 @@ export abstract class Container<
super(type, input, output, parent);
this.embeddableFactories = embeddableFactories;
this.initializeEmbeddables();
this.subscription = this.getInput$().subscribe(() => this.maybeUpdateChildren());
}

public updateInputForChild<EEI extends EmbeddableInput = EmbeddableInput>(
id: string,
changes: Partial<EEI>
) {
if (!this.input.panels[id]) {
throw new Error();
throw new Error(
i18n.translate('embeddableApi.errors.paneldoesNotExist', {
defaultMessage: 'Panel not found.',
})
);
}
const panels = {
panels: {
Expand Down Expand Up @@ -117,11 +126,10 @@ export abstract class Container<
);
this.children[embeddable.id] = embeddable;
this.updateOutput({
...this.output,
embeddableLoaded: {
[panelState.embeddableId]: true,
},
});
} as Partial<O>);
return embeddable;
}

Expand All @@ -145,19 +153,22 @@ export abstract class Container<
this.children[embeddable.id] = embeddable;

this.updateOutput({
...this.output,
embeddableLoaded: {
[panelState.embeddableId]: true,
},
});
} as Partial<O>);
return embeddable;
}

public removeEmbeddable(embeddableId: string) {
// Clean up
const embeddable = this.getChild(embeddableId);
embeddable.destroy();

// Remove references.
delete this.children[embeddableId];

// Update input state.
const changedInput: { panels: { [key: string]: PanelState } } = {
panels: {},
};
Expand All @@ -167,6 +178,8 @@ export abstract class Container<
}
});
this.updateInput({ ...changedInput } as Partial<I>);

// Update output state.
this.updateOutput({
embeddableLoaded: {
...this.output.embeddableLoaded,
Expand Down Expand Up @@ -309,4 +322,47 @@ export abstract class Container<
});
return explicitInput;
}

private onPanelRemoved(id: string) {
// Clean up
const embeddable = this.getChild(id);
embeddable.destroy();

// Remove references.
delete this.children[id];

// Update output state.
this.updateOutput({
embeddableLoaded: {
...this.output.embeddableLoaded,
[id]: undefined,
},
} as Partial<O>);
}

private async onPanelAdded(panel: PanelState) {
const factory = this.embeddableFactories.getFactoryByName(panel.type);
const embeddable = await factory.create<Embeddable>(
this.getInputForChild(panel.embeddableId),
this
);
this.children[embeddable.id] = embeddable;
this.updateOutput({
embeddableLoaded: {
[panel.embeddableId]: true,
},
} as Partial<O>);
return embeddable;
}

private maybeUpdateChildren() {
const allIds = Object.keys({ ...this.input.panels, ...this.children });
allIds.forEach(id => {
if (this.input.panels[id] !== undefined && this.children[id] === undefined) {
this.onPanelAdded(this.input.panels[id]);
} else if (this.input.panels[id] === undefined && this.children[id] !== undefined) {
this.onPanelRemoved(id);
}
});
}
}
Loading

0 comments on commit 1ce9f30

Please sign in to comment.