-
Notifications
You must be signed in to change notification settings - Fork 8.6k
[Discover][Embeddable] Add New Discover session for Dashboards #256293
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
Changes from all commits
2f1630d
5234bd5
1c12eb9
bdbb4ae
40ac12d
5cd10ba
4496413
5406544
f4b142e
cad5d6f
259b249
db85bf2
0615576
e205918
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,96 @@ | ||
| /* | ||
| * 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public | ||
| * License v3.0 only", or the "Server Side Public License, v 1". | ||
| */ | ||
| import { i18n } from '@kbn/i18n'; | ||
| import { v4 as uuidv4 } from 'uuid'; | ||
| import type { ApplicationStart } from '@kbn/core/public'; | ||
| import { | ||
| type EmbeddableApiContext, | ||
| apiCanAccessViewMode, | ||
| apiHasAppContext, | ||
| apiIsOfType, | ||
| getInheritedViewMode, | ||
| } from '@kbn/presentation-publishing'; | ||
|
|
||
| import type { Action, ActionExecutionContext } from '@kbn/ui-actions-plugin/public'; | ||
| import { ADD_PANEL_VISUALIZATION_GROUP, type EmbeddableStart } from '@kbn/embeddable-plugin/public'; | ||
| import type { DiscoverSessionTab } from '@kbn/saved-search-plugin/common'; | ||
| import type { DiscoverAppLocator } from '../../../common'; | ||
| import { ACTION_ADD_DISCOVER_SESSION_PANEL } from '../constants'; | ||
|
|
||
| export class AddDiscoverSessionPanelAction implements Action<EmbeddableApiContext> { | ||
| public id = ACTION_ADD_DISCOVER_SESSION_PANEL; | ||
| public readonly type = ACTION_ADD_DISCOVER_SESSION_PANEL; | ||
| public readonly order = 45; | ||
| public readonly grouping = [ADD_PANEL_VISUALIZATION_GROUP]; | ||
|
|
||
| constructor( | ||
| private readonly application: ApplicationStart, | ||
| private readonly locator: DiscoverAppLocator, | ||
| private readonly embeddable: EmbeddableStart | ||
| ) {} | ||
|
|
||
| getIconType(): string | undefined { | ||
| return 'discoverApp'; | ||
| } | ||
|
|
||
| getDisplayName(): string { | ||
| return i18n.translate('discover.savedSearchEmbeddable.action.addPanel.displayName', { | ||
| defaultMessage: 'Discover session', | ||
| }); | ||
| } | ||
|
|
||
| async execute({ | ||
| embeddable: embeddableApi, | ||
| }: ActionExecutionContext<EmbeddableApiContext>): Promise<void> { | ||
| const { app, path } = await this.locator.getLocation({}); | ||
| const stateTransfer = this.embeddable.getStateTransfer(); | ||
|
|
||
| const valueInput: DiscoverSessionTab = { | ||
| id: uuidv4(), | ||
| label: i18n.translate('discover.savedSearchEmbeddable.action.addPanel.byValueTabName', { | ||
| defaultMessage: 'New by-value Discover session', | ||
| }), | ||
| sort: [], | ||
| columns: [], | ||
| isTextBasedQuery: true, | ||
| grid: {}, | ||
| hideChart: false, | ||
| serializedSearchSource: {}, | ||
| }; | ||
|
|
||
| const appContext = apiHasAppContext(embeddableApi) ? embeddableApi.getAppContext() : undefined; | ||
|
|
||
| stateTransfer.navigateToEditor(app, { | ||
| path, | ||
| state: { | ||
| valueInput, | ||
| originatingApp: appContext?.currentAppId || '', | ||
| originatingPath: appContext?.getCurrentPath?.(), | ||
| }, | ||
| }); | ||
| } | ||
|
|
||
| getDisplayNameTooltip(): string { | ||
| return ''; | ||
| } | ||
|
|
||
| async isCompatible({ embeddable }: ActionExecutionContext<EmbeddableApiContext>) { | ||
| const { capabilities } = this.application; | ||
| const hasDiscoverPermissions = | ||
| (capabilities.discover_v2.show as boolean) || (capabilities.discover_v2.save as boolean); | ||
|
|
||
| if (!hasDiscoverPermissions) return false; | ||
|
|
||
| return ( | ||
| apiCanAccessViewMode(embeddable) && | ||
| getInheritedViewMode(embeddable) === 'edit' && | ||
| apiIsOfType(embeddable, 'dashboard') | ||
| ); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -13,6 +13,24 @@ import type { | |
| import { SEARCH_EMBEDDABLE_TYPE } from '@kbn/discover-utils'; | ||
| import type { EmbeddableEditorState, EmbeddableStateTransfer } from '@kbn/embeddable-plugin/public'; | ||
|
|
||
| /** | ||
| * Specifies the action to be taken for navigating back to an editor. | ||
| */ | ||
| export enum TransferAction { | ||
| /** | ||
| * A Cancel operation. Returns to the editor without modifying the original state. | ||
| */ | ||
| Cancel, | ||
| /** | ||
| * A Save Session operation. Updates the saved session and doesn't pass back any serialised state. | ||
| */ | ||
| SaveSession, | ||
| /** | ||
| * A Save By Value operation. Sends back to the editor the serialised updated state for the embeddable. | ||
| */ | ||
| SaveByValue, | ||
| } | ||
|
|
||
| export class EmbeddableEditorService { | ||
| private embeddableState?: EmbeddableEditorState; | ||
|
|
||
|
|
@@ -27,14 +45,29 @@ export class EmbeddableEditorService { | |
| public getByValueInput = (): DiscoverSessionTab | undefined => | ||
| this.embeddableState?.valueInput as DiscoverSessionTab | undefined; | ||
|
|
||
| /** | ||
| * Resets the embeddable transfer state, ensuring it is cleared in storage and then dropped in memory. | ||
| */ | ||
| public clearEditorState = () => { | ||
| if (this.embeddableState) { | ||
| this.embeddableStateTransfer.clearEditorState('discover'); | ||
| this.embeddableState = undefined; | ||
| } | ||
| }; | ||
|
|
||
| public transferBackToEditor = (state?: SavedSearchByValueAttributes) => { | ||
| public transferBackToEditor(action: TransferAction.Cancel | TransferAction.SaveSession): void; | ||
| public transferBackToEditor( | ||
| action: TransferAction.SaveByValue, | ||
| state: SavedSearchByValueAttributes | ||
| ): void; | ||
| public transferBackToEditor(action: TransferAction, state?: SavedSearchByValueAttributes): void; | ||
|
Comment on lines
+58
to
+63
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're one of few to make good use of function overloading in TS! 😄
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All this would be unnecessary if TS had Rust-like enums and pattern-matching 😅 I'm so rust-brained... |
||
| /** | ||
| * Initiates a navigation back to the editing application, either cancelling the current action to return | ||
| * or passing a state for an embeddable to receive an updated view. | ||
| * | ||
| * **NOTE**: Cancelling will never pass an updated state, so the state param is ignored for cancel actions. | ||
| */ | ||
| public transferBackToEditor(action: TransferAction, state?: SavedSearchByValueAttributes) { | ||
| if (this.embeddableState) { | ||
| const app = this.embeddableState.originatingApp; | ||
| const path = this.embeddableState.originatingPath; | ||
|
|
@@ -43,15 +76,18 @@ export class EmbeddableEditorService { | |
| this.embeddableStateTransfer.clearEditorState('discover'); | ||
| this.embeddableStateTransfer.navigateToWithEmbeddablePackages(app, { | ||
| path, | ||
| state: [ | ||
| { | ||
| type: SEARCH_EMBEDDABLE_TYPE, | ||
| serializedState: { attributes: state }, | ||
| embeddableId: this.embeddableState?.embeddableId, | ||
| }, | ||
| ], | ||
| state: | ||
| action !== TransferAction.Cancel | ||
| ? [ | ||
| { | ||
| type: SEARCH_EMBEDDABLE_TYPE, | ||
| serializedState: { attributes: state }, | ||
| embeddableId: this.embeddableState?.embeddableId, | ||
| }, | ||
| ] | ||
| : [], | ||
| }); | ||
| } | ||
| } | ||
| }; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like this approach 👌