Skip to content

Commit 5abb2c8

Browse files
streamichDosantmattkimeelasticmachineandreadelrio
authored
Drilldowns (#59632)
* Add drilldown wizard components * Dynamic actions (#58216) * feat: 🎸 add DynamicAction and FactoryAction types * feat: 🎸 add Mutable<T> type to @kbn/utility-types * feat: 🎸 add ActionInternal and ActionContract * chore: 🤖 remove unused file * feat: 🎸 improve action interfaces * docs: ✏️ add JSDocs * feat: 🎸 simplify ui_actions interfaces * fix: 🐛 fix TypeScript types * feat: 🎸 add AbstractPresentable interface * feat: 🎸 add AbstractConfigurable interface * feat: 🎸 use AbstractPresentable in ActionInternal * test: 💍 fix ui_actions Jest tests * feat: 🎸 add state container to action * perf: ⚡️ convert MenuItem to React component on Action instance * refactor: 💡 rename AbsractPresentable -> Presentable * refactor: 💡 rename AbstractConfigurable -> Configurable * feat: 🎸 add Storybook to ui_actions * feat: 🎸 add <ErrorConfigureAction> component * feat: 🎸 improve <ConfigureAction> component * chore: 🤖 use .story file extension prefix for Storybook * feat: 🎸 improve <ErrorConfigureAction> component * feat: 🎸 show error if dynamic action has CollectConfig missing * feat: 🎸 render sample action configuration component * feat: 🎸 connect action config to <ConfigureAction> * feat: 🎸 improve <ConfigureAction> stories * test: 💍 add ActionInternal serialize/deserialize tests * feat: 🎸 add ActionContract * feat: 🎸 split action Context into Execution and Presentation * fix: 🐛 fix TypeScript error * refactor: 💡 extract state container hooks to module scope * docs: ✏️ fix typos * chore: 🤖 remove Mutable<t> type * test: 💍 don't cast to any getActions() function * style: 💄 avoid using unnecessary types * chore: 🤖 address PR review comments * chore: 🤖 rename ActionContext generic * chore: 🤖 remove order from state container * chore: 🤖 remove deprecation notice on getHref * test: 💍 fix tests after order field change * remove comments Co-authored-by: Matt Kime <matt@mattki.me> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> * Drilldown context menu (#59638) * fix: 🐛 fix TypeScript error * feat: 🎸 add CONTEXT_MENU_DRILLDOWNS_TRIGGER trigger * fix: 🐛 correctly order context menu items * fix: 🐛 set correct order on drilldown flyout actions * fix: 🐛 clean up context menu building functions * feat: 🎸 add context menu separator action * Add basic ActionFactoryService. Pass data from it into components instead of mocks * Dashboard x pack (#59653) * feat: 🎸 add dashboard_enhanced plugin to x-pack * feat: 🎸 improve context menu separator * feat: 🎸 move drilldown flyout actions to dashboard_enhanced * fix: 🐛 fix exports from ui_actions plugin * feat: 🎸 "implement" registerDrilldown() method * fix ConfigurableBaseConfig type * Implement connected flyout_manage_drilldowns component * Simplify connected flyout manage drilldowns component. Remove intermediate component * clean up data-testid workaround in new components * Connect welcome message to storage Not sure, but use LocalStorage. Didn’t find a way to persist user settings. looks like uiSettings are not user scoped. * require `context` in Presentable. drill context down through wizard components * Drilldown factory (#59823) * refactor: 💡 import storage interface from ui_actions plugin * refactor: 💡 make actions not-dynamic * feat: 🎸 fix TypeScript errors, reshuffle types and code * fix: 🐛 fix more TypeScript errors * fix: 🐛 fix TypeScript import error * Drilldown registration (#59834) * feat: 🎸 improve drilldown registration method * fix: 🐛 set up translations for dashboard_enhanced plugin * Drilldown events 3 (#59854) * feat: 🎸 add serialize/unserialize to action * feat: 🎸 pass in uiActions service into Embeddable * feat: 🎸 merge ui_actions oss and basic plugins * refactor: 💡 move action factory registry to OSS * fix: 🐛 fix TypeScript errors * Drilldown events 4 (#59876) * feat: 🎸 mock sample drilldown execute methods * feat: 🎸 add .dynamicActions manager to Embeddable * feat: 🎸 add first version of dynamic action manager * Drilldown events 5 (#59885) * feat: 🎸 display drilldowns in context menu only on one embed * feat: 🎸 clear dynamic actions from registry when embed unloads * fix: 🐛 fix OSS TypeScript errors * basic integration of components with dynamicActionManager * fix: 🐛 don't overwrite explicitInput with combined input (#59938) * display drilldown count in embeddable edit mode * display drilldown count in embeddable edit mode * improve wizard components. more tests. * partial progress, dashboard drilldowns (#59977) * partial progress, dashboard drilldowns * partial progress, dashboard drilldowns * feat: 🎸 improve dashboard drilldown setup * feat: 🎸 wire in services into dashboard drilldown * chore: 🤖 add Storybook to dashboard_enhanced * feat: 🎸 create presentational <DashboardDrilldownConfig> * test: 💍 add <DashboardDrilldownConfig> stories * test: 💍 use presentation dashboar config component * feat: 🎸 wire in services into React component * docs: ✏️ add README to /components folder * feat: 🎸 increase importance of Dashboard drilldown * feat: 🎸 improve icon definition in drilldowns * chore: 🤖 remove unnecessary comment * chore: 🤖 add todos Co-authored-by: streamich <streamich@gmail.com> * Manage drilldowns toasts. Add basic error handling. * support order in action factory selector * fix column order in manage drilldowns list * remove accidental debug info * bunch of nit ui fixes * Drilldowns reactive action manager (#60099) * feat: 🎸 improve isConfigValid return type * feat: 🎸 make DynamicActionManager reactive * docs: ✏️ add JSDocs to public mehtods of DynamicActionManager * feat: 🎸 make panel top-right corner number badge reactive * fix: 🐛 correctly await for .deleteEvents() * Drilldowns various 2 (#60103) * chore: 🤖 address review comments * test: 💍 fix embeddable_panel.test.tsx tests * chore: 🤖 clean up ActionInternal * chore: 🤖 make isConfigValid a simple predicate * chore: 🤖 fix TypeScript type errors * test: 💍 stub DynamicActionManager tests (#60104) * Drilldowns review 1 (#60139) * refactor: 💡 improve generic types * fix: 🐛 don't overwrite icon * fix: 🐛 fix x-pack TypeScript errors * fix: 🐛 fix TypeScript error * fix: 🐛 correct merge * Drilldowns various 4 (#60264) * feat: 🎸 hide "Create drilldown" from context menu when needed * style: 💄 remove AnyDrilldown type * feat: 🎸 add drilldown factory context * chore: 🤖 remove sample drilldown * fix: 🐛 increase spacing between action factory picker * workaround issue with closing flyout when navigating away Adds overlay just like other flyouts which makes this defect harder to bump in * fix react key issue in action_wizard * don’t open 2 flyouts * fix action order #60138 * Drilldowns reload stored (#60336) * style: 💄 don't use double equals __ * feat: 🎸 add reload$ to ActionStorage interface * feat: 🎸 add reload$ to embeddable event storage * feat: 🎸 add storage syncing to DynamicActionManager * refactor: 💡 use state from DynamicActionManager in React * fix: 🐛 add check for manager being stopped * Drilldowns triggers (#60339) * feat: 🎸 make use of supportedTriggers() * feat: 🎸 pass in context to configuration component * feat: 🎸 augment factory context * fix: 🐛 stop infinite re-rendering * Drilldowns multitrigger (#60357) * feat: 🎸 add support for multiple triggers * feat: 🎸 enable Drilldowns for TSVB Although TSVB brushing event is now broken on master, KibanaApp plans to fix it in 7.7 * "Create drilldown" flyout - design cleanup (#60309) * create drilldown flyout cleanup * remove border from selectedActionFactoryContainer * adjust callout in DrilldownHello * update form labels * remove unused file * fix type error Co-authored-by: Anton Dosov <anton.dosov@elastic.co> * basic unit tests for flyout_create_drildown action * Drilldowns finalize (#60371) * fix: 🐛 align flyout content to left side * fix: 🐛 move context menu item number 1px lower * fix: 🐛 move flyout back nav chevron up * fix: 🐛 fix type check after refactor * basic unit tests for drilldown actions * Drilldowns finalize 2 (#60510) * test: 💍 fix test mock * chore: 🤖 remove unused UiActionsService methods * refactor: 💡 cleanup UiActionsService action registration * fix: 🐛 add missing functionality after refactor * test: 💍 add action factory tests * test: 💍 add DynamicActionManager tests * feat: 🎸 capture error if it happens during initial load * fix: 🐛 register correctly CSV action * feat: 🎸 don't show "OPTIONS" title on drilldown context menus * feat: 🎸 add server-side for x-pack dashboard plugin * feat: 🎸 disable Drilldowns for TSVB * feat: 🎸 enable drilldowns on kibana.yml feature flag * feat: 🎸 add feature flag comment to kibana.yml * feat: 🎸 remove places from drilldown interface * refactor: 💡 remove place in factory context * chore: 🤖 remove doExecute * remove not needed now error_configure_action component * remove workaround for storybook * feat: 🎸 improve DrilldownDefinition interface * style: 💄 replace any by unknown * chore: 🤖 remove any * chore: 🤖 make isConfigValid return type a boolean * refactor: 💡 move getDisplayName to factory, remove deprecated * style: 💄 remove any * feat: 🎸 improve ActionFactoryDefinition * refactor: 💡 change visualize_embeddable params * feat: 🎸 add dashboard dependency to dashboard_enhanced * style: 💄 rename drilldown plugin life-cycle contracts * refactor: 💡 do naming adjustments for dashboard drilldown * fix: 🐛 fix Type error * fix: 🐛 fix TypeScript type errors * test: 💍 fix test after refactor * refactor: 💡 rename context -> placeContext in React component * chore: 🤖 remove setting from kibana.yml * refactor: 💡 change return type of getAction as per review * remove custom css per review * refactor: 💡 rename drilldownCount to eventCount * style: 💄 remove any * refactor: 💡 change how uiActions are passed to vis embeddable * style: 💄 remove unused import Co-authored-by: Anton Dosov <anton.dosov@elastic.co> Co-authored-by: Matt Kime <matt@mattki.me> Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com> Co-authored-by: Andrea Del Rio <delrio.andre@gmail.com>
1 parent e96ed69 commit 5abb2c8

File tree

164 files changed

+5368
-898
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

164 files changed

+5368
-898
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# For more info, see https://help.github.com/articles/about-codeowners/
44

55
# App
6+
/x-pack/legacy/plugins/dashboard_enhanced/ @elastic/kibana-app
67
/x-pack/legacy/plugins/lens/ @elastic/kibana-app
78
/x-pack/legacy/plugins/graph/ @elastic/kibana-app
89
/src/legacy/server/url_shortening/ @elastic/kibana-app

examples/ui_action_examples/public/plugin.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export class UiActionExamplesPlugin
4646
}));
4747

4848
uiActions.registerAction(helloWorldAction);
49-
uiActions.attachAction(helloWorldTrigger.id, helloWorldAction);
49+
uiActions.addTriggerAction(helloWorldTrigger.id, helloWorldAction);
5050
}
5151

5252
public start() {}

examples/ui_actions_explorer/public/app.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,8 +95,7 @@ const ActionsExplorer = ({ uiActionsApi, openModal }: Props) => {
9595
);
9696
},
9797
});
98-
uiActionsApi.registerAction(dynamicAction);
99-
uiActionsApi.attachAction(HELLO_WORLD_TRIGGER_ID, dynamicAction);
98+
uiActionsApi.addTriggerAction(HELLO_WORLD_TRIGGER_ID, dynamicAction);
10099
setConfirmationText(
101100
`You've successfully added a new action: ${dynamicAction.getDisplayName(
102101
{}

examples/ui_actions_explorer/public/plugin.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,21 +79,21 @@ export class UiActionsExplorerPlugin implements Plugin<void, void, {}, StartDeps
7979

8080
const startServices = core.getStartServices();
8181

82-
deps.uiActions.attachAction(
82+
deps.uiActions.addTriggerAction(
8383
USER_TRIGGER,
8484
createPhoneUserAction(async () => (await startServices)[1].uiActions)
8585
);
86-
deps.uiActions.attachAction(
86+
deps.uiActions.addTriggerAction(
8787
USER_TRIGGER,
8888
createEditUserAction(async () => (await startServices)[0].overlays.openModal)
8989
);
9090

91-
deps.uiActions.attachAction(COUNTRY_TRIGGER, viewInMapsAction);
92-
deps.uiActions.attachAction(COUNTRY_TRIGGER, lookUpWeatherAction);
93-
deps.uiActions.attachAction(COUNTRY_TRIGGER, showcasePluggability);
94-
deps.uiActions.attachAction(PHONE_TRIGGER, makePhoneCallAction);
95-
deps.uiActions.attachAction(PHONE_TRIGGER, showcasePluggability);
96-
deps.uiActions.attachAction(USER_TRIGGER, showcasePluggability);
91+
deps.uiActions.addTriggerAction(COUNTRY_TRIGGER, viewInMapsAction);
92+
deps.uiActions.addTriggerAction(COUNTRY_TRIGGER, lookUpWeatherAction);
93+
deps.uiActions.addTriggerAction(COUNTRY_TRIGGER, showcasePluggability);
94+
deps.uiActions.addTriggerAction(PHONE_TRIGGER, makePhoneCallAction);
95+
deps.uiActions.addTriggerAction(PHONE_TRIGGER, showcasePluggability);
96+
deps.uiActions.addTriggerAction(USER_TRIGGER, showcasePluggability);
9797

9898
core.application.register({
9999
id: 'uiActionsExplorer',

src/core/public/overlays/flyout/flyout_service.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ export interface OverlayFlyoutStart {
9191
export interface OverlayFlyoutOpenOptions {
9292
className?: string;
9393
closeButtonAriaLabel?: string;
94+
ownFocus?: boolean;
9495
'data-test-subj'?: string;
9596
}
9697

src/dev/storybook/aliases.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,14 @@
1818
*/
1919

2020
export const storybookAliases = {
21+
advanced_ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js',
2122
apm: 'x-pack/legacy/plugins/apm/scripts/storybook.js',
2223
canvas: 'x-pack/legacy/plugins/canvas/scripts/storybook_new.js',
2324
codeeditor: 'src/plugins/kibana_react/public/code_editor/scripts/storybook.ts',
25+
dashboard_enhanced: 'x-pack/plugins/dashboard_enhanced/scripts/storybook.js',
2426
drilldowns: 'x-pack/plugins/drilldowns/scripts/storybook.js',
2527
embeddable: 'src/plugins/embeddable/scripts/storybook.js',
2628
infra: 'x-pack/legacy/plugins/infra/scripts/storybook.js',
2729
siem: 'x-pack/legacy/plugins/siem/scripts/storybook.js',
28-
ui_actions: 'x-pack/plugins/advanced_ui_actions/scripts/storybook.js',
30+
ui_actions: 'src/plugins/ui_actions/scripts/storybook.js',
2931
};

src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import { PersistedState } from '../../../../../../../plugins/visualizations/publ
4545
import { buildPipeline } from '../legacy/build_pipeline';
4646
import { Vis } from '../vis';
4747
import { getExpressions, getUiActions } from '../services';
48+
import { VisualizationsStartDeps } from '../plugin';
4849
import { VIS_EVENT_TO_TRIGGER } from './events';
4950

5051
const getKeys = <T extends {}>(o: T): Array<keyof T> => Object.keys(o) as Array<keyof T>;
@@ -56,6 +57,7 @@ export interface VisualizeEmbeddableConfiguration {
5657
editable: boolean;
5758
appState?: { save(): void };
5859
uiState?: PersistedState;
60+
uiActions?: VisualizationsStartDeps['uiActions'];
5961
}
6062

6163
export interface VisualizeInput extends EmbeddableInput {
@@ -94,7 +96,7 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
9496

9597
constructor(
9698
timefilter: TimefilterContract,
97-
{ vis, editUrl, indexPatterns, editable }: VisualizeEmbeddableConfiguration,
99+
{ vis, editUrl, indexPatterns, editable, uiActions }: VisualizeEmbeddableConfiguration,
98100
initialInput: VisualizeInput,
99101
parent?: Container
100102
) {
@@ -107,7 +109,8 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
107109
editable,
108110
visTypeName: vis.type.name,
109111
},
110-
parent
112+
parent,
113+
{ uiActions }
111114
);
112115
this.timefilter = timefilter;
113116
this.vis = vis;
@@ -265,6 +268,7 @@ export class VisualizeEmbeddable extends Embeddable<VisualizeInput, VisualizeOut
265268
timeFieldName: this.vis.data.indexPattern!.timeFieldName!,
266269
data: event.data,
267270
};
271+
268272
getUiActions()
269273
.getTrigger(triggerId)
270274
.exec(context);

src/legacy/core_plugins/visualizations/public/np_ready/public/embeddable/visualize_embeddable_factory.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import {
3838
getTimeFilter,
3939
} from '../services';
4040
import { showNewVisModal } from '../wizard';
41+
import { VisualizationsStartDeps } from '../plugin';
4142
import { convertToSerializedVis } from '../saved_visualizations/_saved_vis';
4243

4344
interface VisualizationAttributes extends SavedObjectAttributes {
@@ -52,7 +53,11 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
5253
> {
5354
public readonly type = VISUALIZE_EMBEDDABLE_TYPE;
5455

55-
constructor() {
56+
constructor(
57+
private readonly getUiActions: () => Promise<
58+
Pick<VisualizationsStartDeps, 'uiActions'>['uiActions']
59+
>
60+
) {
5661
super({
5762
savedObjectMetaData: {
5863
name: i18n.translate('visualizations.savedObjectName', { defaultMessage: 'Visualization' }),
@@ -114,6 +119,8 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
114119

115120
const indexPattern = vis.data.indexPattern;
116121
const indexPatterns = indexPattern ? [indexPattern] : [];
122+
const uiActions = await this.getUiActions();
123+
117124
const editable = await this.isEditable();
118125
return new VisualizeEmbeddable(
119126
getTimeFilter(),
@@ -124,6 +131,7 @@ export class VisualizeEmbeddableFactory extends EmbeddableFactory<
124131
editable,
125132
appState: input.appState,
126133
uiState: input.uiState,
134+
uiActions,
127135
},
128136
input,
129137
parent

src/legacy/core_plugins/visualizations/public/np_ready/public/mocks.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* under the License.
1818
*/
1919

20-
import { PluginInitializerContext } from '../../../../../../core/public';
20+
import { CoreSetup, PluginInitializerContext } from '../../../../../../core/public';
2121
import { VisualizationsSetup, VisualizationsStart } from './';
2222
import { VisualizationsPlugin } from './plugin';
2323
import { coreMock } from '../../../../../../core/public/mocks';
@@ -26,6 +26,7 @@ import { expressionsPluginMock } from '../../../../../../plugins/expressions/pub
2626
import { dataPluginMock } from '../../../../../../plugins/data/public/mocks';
2727
import { usageCollectionPluginMock } from '../../../../../../plugins/usage_collection/public/mocks';
2828
import { uiActionsPluginMock } from '../../../../../../plugins/ui_actions/public/mocks';
29+
import { VisualizationsStartDeps } from './plugin';
2930

3031
const createSetupContract = (): VisualizationsSetup => ({
3132
createBaseVisualization: jest.fn(),
@@ -48,7 +49,7 @@ const createStartContract = (): VisualizationsStart => ({
4849
const createInstance = async () => {
4950
const plugin = new VisualizationsPlugin({} as PluginInitializerContext);
5051

51-
const setup = plugin.setup(coreMock.createSetup(), {
52+
const setup = plugin.setup(coreMock.createSetup() as CoreSetup<VisualizationsStartDeps>, {
5253
data: dataPluginMock.createSetupContract(),
5354
expressions: expressionsPluginMock.createSetupContract(),
5455
embeddable: embeddablePluginMock.createSetupContract(),

src/legacy/core_plugins/visualizations/public/np_ready/public/plugin.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export class VisualizationsPlugin
111111
constructor(initializerContext: PluginInitializerContext) {}
112112

113113
public setup(
114-
core: CoreSetup,
114+
core: CoreSetup<VisualizationsStartDeps>,
115115
{ expressions, embeddable, usageCollection, data }: VisualizationsSetupDeps
116116
): VisualizationsSetup {
117117
setUISettings(core.uiSettings);
@@ -120,7 +120,9 @@ export class VisualizationsPlugin
120120
expressions.registerFunction(visualizationFunction);
121121
expressions.registerRenderer(visualizationRenderer);
122122

123-
const embeddableFactory = new VisualizeEmbeddableFactory();
123+
const embeddableFactory = new VisualizeEmbeddableFactory(
124+
async () => (await core.getStartServices())[1].uiActions
125+
);
124126
embeddable.registerEmbeddableFactory(VISUALIZE_EMBEDDABLE_TYPE, embeddableFactory);
125127

126128
return {

0 commit comments

Comments
 (0)