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

Redesign the "Add Panel" Experience #183764

Merged
merged 70 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
08bb84a
Remove quick buttons
cqliu1 Jun 27, 2023
f71278f
Create add panel component
cqliu1 Jun 27, 2023
0e1b2f2
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Jun 27, 2023
31143b6
initial scaffold
eokoneyo May 17, 2024
8bbcd0d
start on grouping panel items
eokoneyo May 20, 2024
fd1521e
leverage toMountPoint for addPanelflyout method
eokoneyo May 21, 2024
092d490
save progress
eokoneyo May 21, 2024
3777727
refactor show new vis method
eokoneyo May 22, 2024
bd22c60
refactor aggregation selection modal to support root mode
eokoneyo May 22, 2024
b554bff
use appropriate name for panel selection file
eokoneyo May 22, 2024
5a7ed7c
create single reference point for add panel trigger ui action
eokoneyo May 23, 2024
a59334a
create common group for emmbeddables, that correlate to visualization…
eokoneyo May 23, 2024
151832b
leverage previously setup grouping to render for panel flyout
eokoneyo May 23, 2024
3baa30c
add panel action for handling picking aggregation based visualizations
eokoneyo May 23, 2024
20b8274
cleanup
eokoneyo May 23, 2024
db94c6b
add missing icons for ml panels
eokoneyo May 24, 2024
aaf02af
visual cleanup of panel render list
eokoneyo May 24, 2024
35aa870
try out placement priority idea for panel group sorting
eokoneyo May 27, 2024
79d5a8f
naive search implementation for add panel
eokoneyo May 27, 2024
f823b95
start on fixing tests
eokoneyo May 27, 2024
65c9d8b
accesibility changes so screen reader gets description for panel items
eokoneyo May 28, 2024
103cfe9
promote search matches to top
eokoneyo May 28, 2024
8fac5b4
fix i18n related issues
eokoneyo May 28, 2024
a920747
accomodation for test expectations
eokoneyo May 29, 2024
1691232
invoke vis type method with flyout close handler
eokoneyo May 29, 2024
2e0d4d7
add data-test-subj for embeddable groups
eokoneyo May 30, 2024
fbe4e2c
exclude observability panels from showing in serverless
eokoneyo May 30, 2024
81f224c
more test fixes
eokoneyo May 30, 2024
b2808c7
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine May 30, 2024
2360668
fix unit tests
eokoneyo May 30, 2024
364776d
handle unintended sideeffect in canvas
eokoneyo May 31, 2024
e9451bb
add expect error for type issue
eokoneyo Jun 3, 2024
75cbd21
include compatibility check for selecting agg based visualization, al…
eokoneyo Jun 5, 2024
8453c7d
leverage preexisting order property to compute placementPriority
eokoneyo Jun 5, 2024
f1eb0df
move add panel trigger constant to ui-action-browser package
eokoneyo Jun 6, 2024
a55acef
change machine learning app name
eokoneyo Jun 6, 2024
fada17b
add fallback group for registered actions without group
eokoneyo Jun 6, 2024
56cff97
improve accesibility for panel selection items navigation
eokoneyo Jun 7, 2024
73c959f
include group item sort ordering
eokoneyo Jun 7, 2024
d706682
Wrap panel labels with EuiToolTip for panel type description
cqliu1 Jun 18, 2024
fe15987
Merge remote-tracking branch 'upstream' into feat/resolve-144418
cqliu1 Jun 18, 2024
da7e80f
Merge branch 'main' into feat/resolve-144418
cqliu1 Jun 18, 2024
aaa5777
Fix maps by value test
cqliu1 Jun 19, 2024
ac0ba4f
Merge remote-tracking branch 'upstream' into feat/resolve-144418
cqliu1 Jun 20, 2024
f5292e6
Add offset for add panel search field
cqliu1 Jun 20, 2024
d9b41bc
Remove unnecessary import
cqliu1 Jun 20, 2024
a0b22fc
Scroll to visType before clicking
cqliu1 Jun 20, 2024
87a0f52
Attempt to fix scrolling on failing map test
cqliu1 Jun 21, 2024
f923bc6
Hide sections that don't match search text
cqliu1 Jun 21, 2024
51194fe
Fix maps by value test
cqliu1 Jun 21, 2024
73356f3
Remove offset
cqliu1 Jun 21, 2024
25ea4e6
Change how hidden sections are handled
cqliu1 Jun 21, 2024
cab3de3
Add message when no panel types match search string
cqliu1 Jun 21, 2024
3720409
Merge remote-tracking branch 'upstream' into feat/resolve-144418
cqliu1 Jun 21, 2024
3291e62
Merge branch 'main' into feat/resolve-144418
cqliu1 Jun 21, 2024
910065f
Remove all references to placementPriority
cqliu1 Jun 21, 2024
48bef80
Move addAggVisAction to visualizations plugin
cqliu1 Jun 21, 2024
be9021e
Remove unused import
cqliu1 Jun 21, 2024
677377e
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Jun 21, 2024
3a0c698
Fix i18n id
cqliu1 Jun 22, 2024
4ee460f
Merge remote-tracking branch 'upstream' into feat/resolve-144418
cqliu1 Jun 24, 2024
de6d165
Fix add agg based vis action originatingApp
cqliu1 Jun 25, 2024
5337820
Add type for COMMON_EMBEDDABLE_GROUPING
cqliu1 Jun 25, 2024
68c1afa
Update compatibility logic for add_agg_vis_action
cqliu1 Jun 25, 2024
f78c1be
Merge remote-tracking branch 'upstream' into feat/resolve-144418
cqliu1 Jun 25, 2024
56a4697
Check for appContext in add_agg_vis_action
cqliu1 Jun 25, 2024
79ea2e8
Fix type errors
cqliu1 Jun 25, 2024
947b2c9
Merge branch 'main' into feat/resolve-144418
cqliu1 Jun 26, 2024
ca83f0c
Change ml options order
cqliu1 Jun 26, 2024
882b7dd
Merge branch 'main' into feat/resolve-144418
cqliu1 Jun 26, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
import { i18n } from '@kbn/i18n';
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError, UiActionsStart } from '@kbn/ui-actions-plugin/public';
import {
IncompatibleActionError,
UiActionsStart,
ADD_PANEL_TRIGGER,
} from '@kbn/ui-actions-plugin/public';
import { embeddableExamplesGrouping } from '../embeddable_examples_grouping';
import { ADD_DATA_TABLE_ACTION_ID, DATA_TABLE_ID } from './constants';

Expand Down Expand Up @@ -39,5 +43,5 @@ export const registerCreateDataTableAction = (uiActions: UiActionsStart) => {
defaultMessage: 'Data table',
}),
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_DATA_TABLE_ACTION_ID);
uiActions.attachAction(ADD_PANEL_TRIGGER, ADD_DATA_TABLE_ACTION_ID);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@ export const embeddableExamplesGrouping = {
id: 'embeddableExamples',
getIconType: () => 'documentation',
getDisplayName: () => 'Embeddable examples',
order: -10,
};
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,11 @@
import { i18n } from '@kbn/i18n';
import { apiCanAddNewPanel } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError, UiActionsStart } from '@kbn/ui-actions-plugin/public';
import {
IncompatibleActionError,
UiActionsStart,
ADD_PANEL_TRIGGER,
} from '@kbn/ui-actions-plugin/public';
import { embeddableExamplesGrouping } from '../embeddable_examples_grouping';
import { ADD_EUI_MARKDOWN_ACTION_ID, EUI_MARKDOWN_ID } from './constants';
import { MarkdownEditorSerializedState } from './types';
Expand Down Expand Up @@ -41,7 +45,7 @@ export const registerCreateEuiMarkdownAction = (uiActions: UiActionsStart) => {
defaultMessage: 'EUI Markdown',
}),
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_EUI_MARKDOWN_ACTION_ID);
uiActions.attachAction(ADD_PANEL_TRIGGER, ADD_EUI_MARKDOWN_ACTION_ID);
if (uiActions.hasTrigger('ADD_CANVAS_ELEMENT_TRIGGER')) {
// Because Canvas is not enabled in Serverless, this trigger might not be registered - only attach
// the create action if the Canvas-specific trigger does indeed exist.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import { i18n } from '@kbn/i18n';
import { apiCanAddNewPanel } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { IncompatibleActionError, ADD_PANEL_TRIGGER } from '@kbn/ui-actions-plugin/public';
import { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin';
import { embeddableExamplesGrouping } from '../embeddable_examples_grouping';
import { ADD_FIELD_LIST_ACTION_ID, FIELD_LIST_ID } from './constants';
Expand All @@ -34,5 +34,5 @@ export const registerCreateFieldListAction = (uiActions: UiActionsPublicStart) =
defaultMessage: 'Field list',
}),
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_FIELD_LIST_ACTION_ID);
uiActions.attachAction(ADD_PANEL_TRIGGER, ADD_FIELD_LIST_ACTION_ID);
};
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { CoreStart } from '@kbn/core/public';
import { i18n } from '@kbn/i18n';
import { apiIsPresentationContainer } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { IncompatibleActionError, ADD_PANEL_TRIGGER } from '@kbn/ui-actions-plugin/public';
import { UiActionsPublicStart } from '@kbn/ui-actions-plugin/public/plugin';
import { embeddableExamplesGrouping } from '../embeddable_examples_grouping';
import {
Expand Down Expand Up @@ -67,5 +67,5 @@ export const registerCreateSavedBookAction = (uiActions: UiActionsPublicStart, c
defaultMessage: 'Book',
}),
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_SAVED_BOOK_ACTION_ID);
uiActions.attachAction(ADD_PANEL_TRIGGER, ADD_SAVED_BOOK_ACTION_ID);
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@

import { apiCanAddNewPanel } from '@kbn/presentation-containers';
import { EmbeddableApiContext } from '@kbn/presentation-publishing';
import { IncompatibleActionError, UiActionsStart } from '@kbn/ui-actions-plugin/public';
import {
IncompatibleActionError,
type UiActionsStart,
ADD_PANEL_TRIGGER,
} from '@kbn/ui-actions-plugin/public';
import { embeddableExamplesGrouping } from '../embeddable_examples_grouping';
import { ADD_SEARCH_ACTION_ID, SEARCH_EMBEDDABLE_ID } from './constants';
import { SearchSerializedState } from './types';
Expand All @@ -33,7 +37,7 @@ export const registerAddSearchPanelAction = (uiActions: UiActionsStart) => {
);
},
});
uiActions.attachAction('ADD_PANEL_TRIGGER', ADD_SEARCH_ACTION_ID);
uiActions.attachAction(ADD_PANEL_TRIGGER, ADD_SEARCH_ACTION_ID);
if (uiActions.hasTrigger('ADD_CANVAS_ELEMENT_TRIGGER')) {
// Because Canvas is not enabled in Serverless, this trigger might not be registered - only attach
// the create action if the Canvas-specific trigger does indeed exist.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,18 @@
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { i18n } from '@kbn/i18n';
import type { Trigger } from '@kbn/ui-actions-plugin/public';
import { Trigger } from '.';

export const ADD_PANEL_TRIGGER = 'ADD_PANEL_TRIGGER';

export const addPanelMenuTrigger: Trigger = {
id: ADD_PANEL_TRIGGER,
title: i18n.translate('dashboard.addPanelMenuTrigger.title', {
title: i18n.translate('uiActions.triggers.dashboard.addPanelMenu.title', {
defaultMessage: 'Add panel menu',
}),
description: i18n.translate('dashboard.addPanelMenuTrigger.description', {
description: i18n.translate('uiActions.triggers.dashboard.addPanelMenu.description', {
defaultMessage: "A new action will appear to the dashboard's add panel menu",
}),
};
1 change: 1 addition & 0 deletions packages/kbn-ui-actions-browser/src/triggers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ export * from './row_click_trigger';
export * from './default_trigger';
export * from './visualize_field_trigger';
export * from './visualize_geo_field_trigger';
export * from './dashboard_app_panel_trigger';
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* 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 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { i18n } from '@kbn/i18n';
import { EmbeddableApiContext, apiHasType, type HasType } from '@kbn/presentation-publishing';
import { COMMON_EMBEDDABLE_GROUPING } from '@kbn/embeddable-plugin/public';
import { Action, IncompatibleActionError } from '@kbn/ui-actions-plugin/public';
import { DASHBOARD_APP_ID } from '../dashboard_constants';
import { pluginServices } from '../services/plugin_services';

const ADD_AGG_VIS_ACTION_ID = 'ADD_AGG_VIS';

type AddAggVisualizationPanelActionApi = HasType;

const isApiCompatible = (api: unknown | null): api is AddAggVisualizationPanelActionApi => {
return apiHasType(api) && api.type === 'dashboard';
};

export class AddAggVisualizationPanelAction implements Action<EmbeddableApiContext> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this action is in the Dashboard plugin and not in the Visualize plugin?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this to the visualizations plugin in 48bef80

public readonly type = ADD_AGG_VIS_ACTION_ID;
public readonly id = ADD_AGG_VIS_ACTION_ID;
public readonly grouping = [COMMON_EMBEDDABLE_GROUPING.legacy];

public readonly order = 20;

private showNewVisModal;

constructor() {
({
visualizations: { showNewVisModal: this.showNewVisModal },
} = pluginServices.getServices());
}

public getIconType() {
return 'visualizeApp';
}

public getDisplayName() {
return i18n.translate('dashboard.uiAction.addAggVis.displayName', {
defaultMessage: 'Aggregation based',
});
}

public async isCompatible({ embeddable }: EmbeddableApiContext) {
return isApiCompatible(embeddable);
}

public execute({ embeddable }: EmbeddableApiContext): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: why not use an async function here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 48bef80

return new Promise((resolve, reject) => {
if (!isApiCompatible(embeddable)) {
return reject(new IncompatibleActionError());
}

this.showNewVisModal({
originatingApp: DASHBOARD_APP_ID,
outsideVisualizeApp: true,
showAggsSelection: true,
onClose: resolve,
});
});
}
}
6 changes: 6 additions & 0 deletions src/plugins/dashboard/public/dashboard_actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import { CoreStart } from '@kbn/core/public';
import { CONTEXT_MENU_TRIGGER, PANEL_NOTIFICATION_TRIGGER } from '@kbn/embeddable-plugin/public';
import { ADD_PANEL_TRIGGER } from '@kbn/ui-actions-plugin/public';

import { DashboardStartDependencies } from '../plugin';
import { AddToLibraryAction } from './add_to_library_action';
Expand All @@ -21,6 +22,7 @@ import { LegacyLibraryNotificationAction } from './legacy_library_notification_a
import { UnlinkFromLibraryAction } from './unlink_from_library_action';
import { LegacyUnlinkFromLibraryAction } from './legacy_unlink_from_library_action';
import { LibraryNotificationAction } from './library_notification_action';
import { AddAggVisualizationPanelAction } from './add_agg_vis_action';

interface BuildAllDashboardActionsProps {
core: CoreStart;
Expand All @@ -46,6 +48,10 @@ export const buildAllDashboardActions = async ({
uiActions.registerAction(panelLevelFiltersNotificationAction);
uiActions.attachAction(PANEL_NOTIFICATION_TRIGGER, panelLevelFiltersNotificationAction.id);

const addAggVisualizationPanelAction = new AddAggVisualizationPanelAction();
uiActions.registerAction(addAggVisualizationPanelAction);
uiActions.attachAction(ADD_PANEL_TRIGGER, addAggVisualizationPanelAction.id);

if (share) {
const ExportCSVPlugin = new ExportCSVAction();
uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, ExportCSVPlugin);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import { getMockPresentationContainer } from '@kbn/presentation-containers/mocks';
import { getAddPanelActionMenuItems } from './add_panel_action_menu_items';
import { getAddPanelActionMenuItemsGroup } from './add_panel_action_menu_items';

describe('getAddPanelActionMenuItems', () => {
it('returns the items correctly', async () => {
Expand Down Expand Up @@ -54,52 +54,62 @@ describe('getAddPanelActionMenuItems', () => {
],
},
];
const [items, grouped] = getAddPanelActionMenuItems(
const grouped = getAddPanelActionMenuItemsGroup(
getMockPresentationContainer(),
registeredActions,
jest.fn()
);
expect(items).toStrictEqual([
{
'data-test-subj': 'create-action-Action name',
icon: 'pencil',
name: 'Action name',
onClick: expect.any(Function),
toolTipContent: 'Action tooltip',
},
]);

expect(grouped).toStrictEqual({
groupedAddPanelAction: {
id: 'groupedAddPanelAction',
title: 'Custom group',
icon: 'logoElasticsearch',
placementPriority: 0,
'data-test-subj': 'dashboardEditorMenu-groupedAddPanelActionGroup',
items: [
{
'data-test-subj': 'create-action-Action name 01',
icon: 'pencil',
id: 'TEST_ACTION_01',
name: 'Action name 01',
onClick: expect.any(Function),
toolTipContent: 'Action tooltip',
description: 'Action tooltip',
placementPriority: 0,
},
{
'data-test-subj': 'create-action-Action name',
icon: 'empty',
id: 'TEST_ACTION_02',
name: 'Action name',
onClick: expect.any(Function),
description: 'Action tooltip',
placementPriority: 0,
},
],
},
other: {
id: 'other',
title: 'Other',
placementPriority: -1,
'data-test-subj': 'dashboardEditorMenu-otherGroup',
items: [
{
id: 'ACTION_CREATE_ESQL_CHART',
name: 'Action name',
icon: 'pencil',
description: 'Action tooltip',
onClick: expect.any(Function),
toolTipContent: 'Action tooltip',
'data-test-subj': 'create-action-Action name',
placementPriority: 0,
},
],
},
});
});

it('returns empty array if no actions have been registered', async () => {
const [items, grouped] = getAddPanelActionMenuItems(
getMockPresentationContainer(),
[],
jest.fn()
);
expect(items).toStrictEqual([]);
const grouped = getAddPanelActionMenuItemsGroup(getMockPresentationContainer(), [], jest.fn());

expect(grouped).toStrictEqual({});
});
});
Loading