Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Embeddable API V2: Infrastructure changes necessary to support actions #35622

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
41 commits
Select commit Hold shift + click to select a range
8029518
Embeddable API Plugin
stacey-gammon Apr 25, 2019
a6a10d2
Fix issue with errorembeddable children not receiving updates from pa…
stacey-gammon May 22, 2019
56f30a2
Type changes in response to review comments
stacey-gammon May 22, 2019
603f451
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 22, 2019
1dcfe7e
Get rid of ExecuteActionContext, just use ActionContext
stacey-gammon May 22, 2019
4c7b29f
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 22, 2019
6d2b773
Go back to default export because of #32149
stacey-gammon May 22, 2019
c37a16c
Fix es import path error… again
stacey-gammon May 23, 2019
1be7bbc
Use new registry interface and do some functional refactoring
stacey-gammon May 23, 2019
ca8792b
Fix bug with output state losing instance data and add jest test
stacey-gammon May 23, 2019
14cd8b2
remove unnecessary changes for a table row click trigger
stacey-gammon May 23, 2019
d6610b2
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 23, 2019
842aebb
Remove unnecessary changes to a file
stacey-gammon May 23, 2019
808d5dd
Remove trackUiMetric calls from PR 1
stacey-gammon May 23, 2019
f98c591
Remove unused translations
stacey-gammon May 23, 2019
ec6f778
dashboard mode improvements
stacey-gammon May 23, 2019
3e646ea
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 23, 2019
7a01480
Fix a bad merge, these changes were lost
stacey-gammon May 23, 2019
01fee75
Fix bug with refresh timer not working
stacey-gammon May 24, 2019
80d8b46
Fix saved searches not refreshing with auto interval on.
stacey-gammon May 28, 2019
0fff4b3
Fix map embeddable not updating with auto refresh interval on.
stacey-gammon May 28, 2019
1490a4d
Type fix
stacey-gammon May 28, 2019
8beb278
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 28, 2019
7e2bc5f
Adjust bad import path in code merged from master, and update yarn
stacey-gammon May 28, 2019
7a91eb8
Get rid of what I think is an unnecessary hack, since the courier.fet…
stacey-gammon May 28, 2019
2e58f39
Track jest coverage for all core plugins
stacey-gammon May 28, 2019
256c553
Update sass based on review comments
stacey-gammon May 29, 2019
a52db94
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 29, 2019
3dc4eff
Use async fn instead of Promise.resolve
stacey-gammon May 29, 2019
d9b4ae2
clean up and add comments to embeddable_child_panel
stacey-gammon May 29, 2019
65426e1
Fix issue with panels not resizing. Fixes reporting
stacey-gammon May 29, 2019
6a7e4b4
Merge branch 'master' of github.com:elastic/kibana into 2019-04-25-em…
stacey-gammon May 29, 2019
b4af4b5
Adjust import paths, remove need for custom tsconfig rule
stacey-gammon May 29, 2019
6624128
Migrate export csv action
stacey-gammon May 29, 2019
cb28fb0
use relative paths in all test files, the tsconfig path doesn’t work …
stacey-gammon May 29, 2019
76372e7
Can’t use relative paths into oss, breaks yarn build
stacey-gammon May 29, 2019
7c2703b
Update module name mapper so jest tests work with imports like `plugi…
stacey-gammon May 30, 2019
f02e22a
Put back sass that made expanded panel mode work.
stacey-gammon May 30, 2019
e2ba898
Fix build issues with static imports from xpack into oss
stacey-gammon May 30, 2019
815bfd8
Reorder moduleNameMapper resolutions to get jest tests to pass
stacey-gammon May 30, 2019
f069b06
Small clean up
stacey-gammon May 31, 2019
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
10 changes: 9 additions & 1 deletion src/dev/jest/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,25 @@ export default {
'<rootDir>/src/test_utils',
'<rootDir>/test/functional/services/remote',
],

collectCoverageFrom: [
'packages/kbn-ui-framework/src/components/**/*.js',
'!packages/kbn-ui-framework/src/components/index.js',
'!packages/kbn-ui-framework/src/components/**/*/index.js',
'packages/kbn-ui-framework/src/services/**/*.js',
'!packages/kbn-ui-framework/src/services/index.js',
'!packages/kbn-ui-framework/src/services/**/*/index.js',
'src/legacy/core_plugins/metrics/**/*.js'
'src/legacy/core_plugins/**/*.js',
'src/legacy/core_plugins/**/*.jsx',
'src/legacy/core_plugins/**/*.ts',
'src/legacy/core_plugins/**/*.tsx',
'!src/legacy/core_plugins/**/__test__/**/*',
'!src/legacy/core_plugins/**/__snapshots__/**/*',
],

moduleNameMapper: {
'^plugins/([^\/.]*)/(.*)': '<rootDir>/src/legacy/core_plugins/$1/public/$2',
'^plugins/([^\/.]*)': '<rootDir>/src/legacy/core_plugins/$1/public',
'^ui/(.*)': '<rootDir>/src/legacy/ui/public/$1',
'^uiExports/(.*)': '<rootDir>/src/dev/jest/mocks/file_mock.js',
'^test_utils/(.*)': '<rootDir>/src/test_utils/public/$1',
Expand Down
31 changes: 31 additions & 0 deletions src/legacy/core_plugins/dashboard_embeddable/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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 { resolve } from 'path';

// eslint-disable-next-line import/no-default-export
export default function(kibana: any) {
return new kibana.Plugin({
uiExports: {
embeddableActions: ['plugins/dashboard_embeddable/actions/expand_panel_action'],
embeddableFactories: ['plugins/dashboard_embeddable/embeddable/dashboard_container_factory'],
styleSheetPaths: resolve(__dirname, 'public/index.scss'),
},
});
}
4 changes: 4 additions & 0 deletions src/legacy/core_plugins/dashboard_embeddable/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"name": "dashboard_embeddable",
"version": "kibana"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 { QueryLanguageType, ViewMode, EmbeddableInput } from 'plugins/embeddable_api';
import { DashboardContainerInput, DashboardPanelState } from '../embeddable';

export function getSampleDashboardInput(
overrides?: Partial<DashboardContainerInput>
): DashboardContainerInput {
return {
id: '123',
filters: [],
useMargins: false,
isFullScreenMode: false,
title: 'My Dashboard',
query: {
language: QueryLanguageType.KUERY,
query: 'hi',
},
timeRange: {
to: 'now',
from: 'now-15m',
},
viewMode: ViewMode.VIEW,
panels: {},
...overrides,
};
}

export function getSampleDashboardPanel<TEmbeddableInput extends EmbeddableInput = EmbeddableInput>(
overrides: Partial<DashboardPanelState<TEmbeddableInput>> & { embeddableId: string; type: string }
): DashboardPanelState {
return {
gridData: {
h: 15,
w: 15,
x: 0,
y: 0,
i: overrides.embeddableId,
},
embeddableId: overrides.embeddableId,
type: overrides.type,
explicitInput: overrides.explicitInput || {},
...overrides,
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
* under the License.
*/

export { DashboardGridContainer as DashboardGrid } from './dashboard_grid_container';
export { getSampleDashboardInput, getSampleDashboardPanel } from './get_sample_dashboard_input';
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/*
* 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.
*/

jest.mock('ui/metadata', () => ({
metadata: {
branch: 'my-metadata-branch',
version: 'my-metadata-version',
},
}));

jest.mock('ui/capabilities', () => ({
uiCapabilities: {
visualize: {
save: true,
},
},
}));

import { EmbeddableFactoryRegistry, isErrorEmbeddable } from '../../../embeddable_api/public';
import { ExpandPanelAction } from './expand_panel_action';
import {
ContactCardEmbeddable,
CONTACT_CARD_EMBEDDABLE,
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
ContactCardEmbeddableFactory,
} from '../../../embeddable_api/public/__test__/index';
import { DashboardContainer } from '../embeddable';
import { getSampleDashboardInput, getSampleDashboardPanel } from '../__test__';

const embeddableFactories = new EmbeddableFactoryRegistry();
embeddableFactories.registerFactory(new ContactCardEmbeddableFactory());

let container: DashboardContainer;
let embeddable: ContactCardEmbeddable;

beforeEach(async () => {
container = new DashboardContainer(
getSampleDashboardInput({
panels: {
'123': getSampleDashboardPanel<ContactCardEmbeddableInput>({
embeddableId: '123',
explicitInput: { firstName: 'Sam' },
type: CONTACT_CARD_EMBEDDABLE,
}),
},
}),
embeddableFactories
);

const contactCardEmbeddable = await container.addNewEmbeddable<
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
ContactCardEmbeddable
>(CONTACT_CARD_EMBEDDABLE, {
firstName: 'Kibana',
});

if (isErrorEmbeddable(contactCardEmbeddable)) {
throw new Error('Failed to create embeddable');
} else {
embeddable = contactCardEmbeddable;
}
});

test('Sets the embeddable expanded panel id on the parent', async () => {
const expandPanelAction = new ExpandPanelAction();

expect(container.getInput().expandedPanelId).toBeUndefined();

expandPanelAction.execute({ embeddable });

expect(container.getInput().expandedPanelId).toBe(embeddable.id);
});

test('Is not compatible when embeddable is not in a dashboard container', async () => {
const action = new ExpandPanelAction();
expect(
await action.isCompatible({
embeddable: new ContactCardEmbeddable({ firstName: 'sue', id: '123' }),
})
).toBe(false);
});

test('Execute throws an error when called with an embeddable not in a parent', async () => {
const action = new ExpandPanelAction();
async function check() {
await action.execute({ embeddable: container });
}
await expect(check()).rejects.toThrow(Error);
});

test('Returns title', async () => {
const action = new ExpandPanelAction();
expect(action.getDisplayName({ embeddable })).toBeDefined();
});

test('Returns an icon', async () => {
const action = new ExpandPanelAction();
expect(action.getIcon({ embeddable })).toBeDefined();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* 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 { EuiIcon } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import {
Action,
actionRegistry,
IEmbeddable,
CONTEXT_MENU_TRIGGER,
triggerRegistry,
ActionContext,
attachAction,
IncompatibleActionError,
} from 'plugins/embeddable_api';
import React from 'react';
import { DASHBOARD_CONTAINER_TYPE, DashboardContainer } from '../embeddable';

export const EXPAND_PANEL_ACTION = 'togglePanel';

function isDashboard(
embeddable: IEmbeddable | DashboardContainer
): embeddable is DashboardContainer {
return (embeddable as DashboardContainer).type === DASHBOARD_CONTAINER_TYPE;
}

function isExpanded(embeddable: IEmbeddable) {
if (!embeddable.parent || !isDashboard(embeddable.parent)) {
throw new IncompatibleActionError();
}

return embeddable.id === embeddable.parent.getInput().expandedPanelId;
}

export class ExpandPanelAction extends Action {
public readonly type = EXPAND_PANEL_ACTION;

constructor() {
super(EXPAND_PANEL_ACTION);
this.order = 7;
}

public getDisplayName({ embeddable }: ActionContext) {
if (!embeddable.parent || !isDashboard(embeddable.parent)) {
throw new IncompatibleActionError();
}

return isExpanded(embeddable)
? i18n.translate('kbn.embeddable.actions.toggleExpandPanel.expandedDisplayName', {
defaultMessage: 'Minimize',
})
: i18n.translate('kbn.embeddable.actions.toggleExpandPanel.notExpandedDisplayName', {
defaultMessage: 'Full screen',
});
}

public getIcon({ embeddable }: ActionContext) {
if (!embeddable.parent || !isDashboard(embeddable.parent)) {
throw new IncompatibleActionError();
}
// TODO: use 'minimize' when an eui-icon of such is available.
return <EuiIcon type={isExpanded(embeddable) ? 'expand' : 'expand'} />;
}

public async isCompatible({ embeddable }: ActionContext) {
return Boolean(embeddable.parent && isDashboard(embeddable.parent));
}

public execute({ embeddable }: ActionContext) {
if (!embeddable.parent || !isDashboard(embeddable.parent)) {
throw new IncompatibleActionError();
}
const newValue = isExpanded(embeddable) ? undefined : embeddable.id;
embeddable.parent.updateInput({
expandedPanelId: newValue,
});
}
}

actionRegistry.set(EXPAND_PANEL_ACTION, new ExpandPanelAction());

attachAction(triggerRegistry, {
triggerId: CONTEXT_MENU_TRIGGER,
actionId: EXPAND_PANEL_ACTION,
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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.
*/
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
@import './viewport/index';
@import './panel/index';
@import './grid/index';
Loading