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

Drilldown demo 2 #64300

Merged
merged 25 commits into from
Apr 28, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c68a846
chore: 🤖 add example of Discover drilldown to sample plugin
streamich Apr 16, 2020
9659d34
fix: 🐛 show drilldowns with higher "order" first
streamich Apr 16, 2020
5ada60f
feat: 🎸 add createStartServicesGetter() to /public kibana_util
streamich Apr 16, 2020
aa103a1
feat: 🎸 load index patterns in Discover drilldown
streamich Apr 16, 2020
4adecf0
feat: 🎸 add toggle for index pattern selection
streamich Apr 16, 2020
f8006ae
feat: 🎸 add spacer to separate unrelated config fields
streamich Apr 16, 2020
c894caa
fix: 🐛 correctly configre setup core
streamich Apr 16, 2020
ab3deb7
feat: 🎸 navigate to correct index pattern
streamich Apr 16, 2020
8f72315
chore: 🤖 fix type check errors
streamich Apr 16, 2020
fd96937
fix: 🐛 make index pattern select full width
streamich Apr 16, 2020
b20fd1e
fix: 🐛 add getHref support
streamich Apr 16, 2020
418cab9
feat: 🎸 add example plugin ability to X-Pack
streamich Apr 17, 2020
fcd796a
chore: 🤖 catch up with master
streamich Apr 23, 2020
0f6cee2
refactor: 💡 move Discover drilldown example to X-Pack
streamich Apr 23, 2020
7f5b00e
feat: 🎸 add dashboard-to-url drilldown example
streamich Apr 23, 2020
c337006
feat: 🎸 add new tab support for URL drilldown
streamich Apr 23, 2020
2860aa6
feat: 🎸 add "hello world" drilldown example
streamich Apr 23, 2020
b6e8e51
docs: ✏️ add README
streamich Apr 23, 2020
ddd9eb4
feat: 🎸 add getHref support
streamich Apr 23, 2020
7b1a88e
Merge branch 'drilldowns' into drilldown-demo-2
elasticmachine Apr 24, 2020
73c12d4
chore: 🤖 cleanup after moving examples to X-Pack
streamich Apr 24, 2020
66a680b
Merge branch 'drilldowns' into drilldown-demo-2
elasticmachine Apr 26, 2020
84faa0e
docs: ✏️ add to README.md info on how to find drilldowns
streamich Apr 28, 2020
076f2d7
Merge branch 'drilldowns' into drilldown-demo-2
elasticmachine Apr 28, 2020
1e2435b
Merge branch 'drilldowns' into drilldown-demo-2
elasticmachine Apr 28, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"data": "src/plugins/data",
"embeddableApi": "src/plugins/embeddable",
"embeddableExamples": "examples/embeddable_examples",
"uiActionsExamples": "examples/ui_action_examples",
"share": "src/plugins/share",
"home": "src/plugins/home",
"charts": "src/plugins/charts",
Expand Down
3 changes: 1 addition & 2 deletions examples/ui_action_examples/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@
*/

import { UiActionExamplesPlugin } from './plugin';
import { PluginInitializer } from '../../../src/core/public';

export const plugin: PluginInitializer<void, void> = () => new UiActionExamplesPlugin();
export const plugin = () => new UiActionExamplesPlugin();

export { HELLO_WORLD_TRIGGER_ID } from './hello_world_trigger';
export { ACTION_HELLO_WORLD } from './hello_world_action';
21 changes: 15 additions & 6 deletions examples/ui_action_examples/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,19 @@
* under the License.
*/

import { Plugin, CoreSetup } from '../../../src/core/public';
import { UiActionsSetup } from '../../../src/plugins/ui_actions/public';
import { Plugin, CoreSetup, CoreStart } from '../../../src/core/public';
import { UiActionsSetup, UiActionsStart } from '../../../src/plugins/ui_actions/public';
import { createHelloWorldAction, ACTION_HELLO_WORLD } from './hello_world_action';
import { helloWorldTrigger, HELLO_WORLD_TRIGGER_ID } from './hello_world_trigger';

interface UiActionExamplesSetupDependencies {
export interface UiActionExamplesSetupDependencies {
uiActions: UiActionsSetup;
}

export interface UiActionExamplesStartDependencies {
uiActions: UiActionsStart;
}

declare module '../../../src/plugins/ui_actions/public' {
export interface TriggerContextMapping {
[HELLO_WORLD_TRIGGER_ID]: {};
Expand All @@ -37,8 +41,12 @@ declare module '../../../src/plugins/ui_actions/public' {
}

export class UiActionExamplesPlugin
implements Plugin<void, void, UiActionExamplesSetupDependencies> {
public setup(core: CoreSetup, { uiActions }: UiActionExamplesSetupDependencies) {
implements
Plugin<void, void, UiActionExamplesSetupDependencies, UiActionExamplesStartDependencies> {
public setup(
core: CoreSetup<UiActionExamplesStartDependencies>,
{ uiActions }: UiActionExamplesSetupDependencies
) {
uiActions.registerTrigger(helloWorldTrigger);

const helloWorldAction = createHelloWorldAction(async () => ({
Expand All @@ -49,6 +57,7 @@ export class UiActionExamplesPlugin
uiActions.addTriggerAction(helloWorldTrigger.id, helloWorldAction);
}

public start() {}
public start(core: CoreStart, plugins: UiActionExamplesStartDependencies) {}

public stop() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,14 @@ const indexPatternCache = createIndexPatternCache();

type IndexPatternCachedFieldType = 'id' | 'title';

export interface IndexPatternSavedObjectAttrs {
title: string;
}

export class IndexPatternsService {
private config: IUiSettingsClient;
private savedObjectsClient: SavedObjectsClientContract;
private savedObjectsCache?: Array<SimpleSavedObject<Record<string, any>>> | null;
private savedObjectsCache?: Array<SimpleSavedObject<IndexPatternSavedObjectAttrs>> | null;
private apiClient: IndexPatternsApiClient;
ensureDefaultIndexPattern: EnsureDefaultIndexPattern;

Expand All @@ -53,7 +57,7 @@ export class IndexPatternsService {

private async refreshSavedObjectsCache() {
this.savedObjectsCache = (
await this.savedObjectsClient.find<Record<string, any>>({
await this.savedObjectsClient.find<IndexPatternSavedObjectAttrs>({
type: 'index-pattern',
fields: ['title'],
perPage: 10000,
Expand Down
1 change: 1 addition & 0 deletions x-pack/.i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"paths": {
"xpack.actions": "plugins/actions",
"xpack.advancedUiActions": "plugins/advanced_ui_actions",
"xpack.uiActionsEnhanced": "examples/ui_actions_enhanced_examples",
"xpack.alerting": "plugins/alerting",
"xpack.alertingBuiltins": "plugins/alerting_builtins",
"xpack.apm": ["legacy/plugins/apm", "plugins/apm"],
Expand Down
37 changes: 35 additions & 2 deletions x-pack/examples/ui_actions_enhanced_examples/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,36 @@
## Ui actions enhanced examples
# Ui actions enhanced examples

To run this example, use the command `yarn start --run-examples`.
To run this example plugin, use the command `yarn start --run-examples`.

streamich marked this conversation as resolved.
Show resolved Hide resolved

## Drilldown examples

This plugin holds few examples on how to add drilldown types to dashboard.

To play with drilldowns, open any dashboard, click "Edit" to put it in *edit mode*.
Now when opening context menu of dashboard panels you should see "Create drilldown" option.

![image](https://user-images.githubusercontent.com/9773803/80460907-c2ef7880-8934-11ea-8400-533bb9d57e36.png)

Once you click "Create drilldown" you should be able to see drilldowns added by
this sample plugin.

![image](https://user-images.githubusercontent.com/9773803/80460408-131a0b00-8934-11ea-81e4-137e9e33f34b.png)


### `dashboard_hello_world_drilldown`

`dashboard_hello_world_drilldown` is the most basic "hello world" example showing
how a drilldown can be built, all in one file.

### `dashboard_to_url_drilldown`

`dashboard_to_url_drilldown` is a good starting point for build a drilldown
that navigates somewhere externally.

One can see how middle-click or Ctrl + click behavior could be supported using
`getHref` field.

### `dashboard_to_discover_drilldown`

`dashboard_to_discover_drilldown` shows how a real-world drilldown could look like.
2 changes: 1 addition & 1 deletion x-pack/examples/ui_actions_enhanced_examples/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"configPath": ["ui_actions_enhanced_examples"],
"server": false,
"ui": true,
"requiredPlugins": ["uiActions", "data"],
"requiredPlugins": ["uiActions", "drilldowns", "data"],
"optionalPlugins": []
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
This folder contains a one-file example of the most basic drilldown implementation.
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* 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 React from 'react';
import { EuiFormRow, EuiFieldText } from '@elastic/eui';
import { reactToUiComponent } from '../../../../../src/plugins/kibana_react/public';
import { DrilldownDefinition as Drilldown } from '../../../../plugins/drilldowns/public';
import {
EmbeddableContext,
RangeSelectTriggerContext,
ValueClickTriggerContext,
} from '../../../../../src/plugins/embeddable/public';
import { UiActionsCollectConfigProps } from '../../../../../src/plugins/ui_actions/public';

export type ActionContext = RangeSelectTriggerContext | ValueClickTriggerContext;

export interface Config {
name: string;
}

const SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN = 'SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN';

export class DashboardHelloWorldDrilldown
implements Drilldown<Config, EmbeddableContext, ActionContext> {
public readonly id = SAMPLE_DASHBOARD_HELLO_WORLD_DRILLDOWN;

public readonly order = 6;

public readonly getDisplayName = () => 'Say hello drilldown';

public readonly euiIcon = 'cheer';

private readonly ReactCollectConfig: React.FC<UiActionsCollectConfigProps<Config>> = ({
config,
onConfig,
}) => (
<EuiFormRow label="Enter your name" fullWidth>
<EuiFieldText
fullWidth
value={config.name}
onChange={event => onConfig({ ...config, name: event.target.value })}
/>
</EuiFormRow>
);

public readonly CollectConfig = reactToUiComponent(this.ReactCollectConfig);

public readonly createConfig = () => ({
name: '',
});

public readonly isConfigValid = (config: Config): config is Config => {
return !!config.name;
};

public readonly execute = async (config: Config, context: ActionContext) => {
alert(`Hello, ${config.name}`);
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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 React, { useState, useEffect } from 'react';
import useMountedState from 'react-use/lib/useMountedState';
import { CollectConfigProps } from './types';
import { DiscoverDrilldownConfig, IndexPatternItem } from './components/discover_drilldown_config';
import { Params } from './drilldown';

export interface CollectConfigContainerProps extends CollectConfigProps {
params: Params;
}

export const CollectConfigContainer: React.FC<CollectConfigContainerProps> = ({
config,
onConfig,
params: { start },
}) => {
const isMounted = useMountedState();
const [indexPatterns, setIndexPatterns] = useState<IndexPatternItem[]>([]);

useEffect(() => {
(async () => {
const indexPatternSavedObjects = await start().plugins.data.indexPatterns.getCache();
if (!isMounted()) return;
setIndexPatterns(
indexPatternSavedObjects
? indexPatternSavedObjects.map(indexPattern => ({
id: indexPattern.id,
title: indexPattern.attributes.title,
}))
: []
);
})();
}, [isMounted, start]);

return (
<DiscoverDrilldownConfig
activeIndexPatternId={config.indexPatternId}
indexPatterns={indexPatterns}
onIndexPatternSelect={indexPatternId => {
onConfig({ ...config, indexPatternId });
}}
customIndexPattern={config.customIndexPattern}
onCustomIndexPatternToggle={() =>
onConfig({
...config,
customIndexPattern: !config.customIndexPattern,
indexPatternId: undefined,
})
}
carryFiltersAndQuery={config.carryFiltersAndQuery}
onCarryFiltersAndQueryToggle={() =>
onConfig({
...config,
carryFiltersAndQuery: !config.carryFiltersAndQuery,
})
}
carryTimeRange={config.carryTimeRange}
onCarryTimeRangeToggle={() =>
onConfig({
...config,
carryTimeRange: !config.carryTimeRange,
})
}
/>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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 React from 'react';
import { EuiFormRow, EuiSelect, EuiSwitch, EuiSpacer } from '@elastic/eui';
import { txtChooseDestinationIndexPattern } from './i18n';

export interface IndexPatternItem {
id: string;
title: string;
}

export interface DiscoverDrilldownConfigProps {
activeIndexPatternId?: string;
indexPatterns: IndexPatternItem[];
onIndexPatternSelect: (indexPatternId: string) => void;
customIndexPattern?: boolean;
onCustomIndexPatternToggle?: () => void;
carryFiltersAndQuery?: boolean;
onCarryFiltersAndQueryToggle?: () => void;
carryTimeRange?: boolean;
onCarryTimeRangeToggle?: () => void;
}

export const DiscoverDrilldownConfig: React.FC<DiscoverDrilldownConfigProps> = ({
activeIndexPatternId,
indexPatterns,
onIndexPatternSelect,
customIndexPattern,
onCustomIndexPatternToggle,
carryFiltersAndQuery,
onCarryFiltersAndQueryToggle,
carryTimeRange,
onCarryTimeRangeToggle,
}) => {
return (
<>
{!!onCustomIndexPatternToggle && (
<>
<EuiFormRow hasChildLabel={false}>
<EuiSwitch
name="customIndexPattern"
label="Use custom index pattern"
checked={!!customIndexPattern}
onChange={onCustomIndexPatternToggle}
/>
</EuiFormRow>
{!!customIndexPattern && (
<EuiFormRow fullWidth label={txtChooseDestinationIndexPattern}>
<EuiSelect
name="selectDashboard"
hasNoInitialSelection={true}
fullWidth
options={[
{ id: '', text: 'Pick one...' },
...indexPatterns.map(({ id, title }) => ({ value: id, text: title })),
]}
value={activeIndexPatternId || ''}
onChange={e => onIndexPatternSelect(e.target.value)}
/>
</EuiFormRow>
)}
<EuiSpacer size="xl" />
</>
)}

{!!onCarryFiltersAndQueryToggle && (
<EuiFormRow hasChildLabel={false}>
<EuiSwitch
name="carryFiltersAndQuery"
label="Carry over filters and query"
checked={!!carryFiltersAndQuery}
onChange={onCarryFiltersAndQueryToggle}
/>
</EuiFormRow>
)}
{!!onCarryTimeRangeToggle && (
<EuiFormRow hasChildLabel={false}>
<EuiSwitch
name="carryTimeRange"
label="Carry over time range"
checked={!!carryTimeRange}
onChange={onCarryTimeRangeToggle}
/>
</EuiFormRow>
)}
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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 { i18n } from '@kbn/i18n';

export const txtChooseDestinationIndexPattern = i18n.translate(
'xpack.uiActionsEnhanced.components.DiscoverDrilldownConfig.chooseIndexPattern',
{
defaultMessage: 'Choose destination index pattern',
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*
* 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.
*/

export * from './discover_drilldown_config';
Loading