Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 @@ -140,7 +140,8 @@ export const useLookupIndexCommand = (
getLookupIndices: (() => Promise<{ indices: IndexAutocompleteItem[] }>) | undefined,
query: AggregateQuery,
onIndexCreated: (resultQuery: string) => Promise<void>,
onNewFieldsAddedToIndex?: (indexName: string) => void
onNewFieldsAddedToIndex?: (indexName: string) => void,
onOpenIndexInDiscover?: EditLookupIndexContentContext['onOpenIndexInDiscover']
) => {
const { euiTheme } = useEuiTheme();
const {
Expand Down Expand Up @@ -296,9 +297,10 @@ export const useLookupIndexCommand = (
indexHasNewFields
);
},
onOpenIndexInDiscover,
} as EditLookupIndexContentContext);
},
[onFlyoutClose, uiActions]
[onFlyoutClose, onOpenIndexInDiscover, uiActions]
);

const openFlyoutRef = useRef(openFlyout);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const ESQLEditorInternal = function ESQLEditor({
disableAutoFocus,
controlsContext,
esqlVariables,
onOpenQueryInNewTab,
Copy link
Contributor

Choose a reason for hiding this comment

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

Why in one component is onOpenQuery and on the other is onOpenIndex ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

From the index editor point of view, it wants to open a specific index in a new tab.
From the esql editor point of view, it provides a general purpose callback to open any kind of query in a new tab.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see, makes sense

expandToFitQueryOnMount,
dataErrorsControl,
formLabel,
Expand Down Expand Up @@ -769,7 +770,8 @@ const ESQLEditorInternal = function ESQLEditor({
getJoinIndices,
query,
onLookupIndexCreate,
onNewFieldsAddedToLookupIndex
onNewFieldsAddedToLookupIndex,
onOpenQueryInNewTab
);

useDebounceWithOptions(
Expand Down
2 changes: 2 additions & 0 deletions src/platform/packages/private/kbn-esql-editor/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@ export interface ESQLEditorProps {
disableAutoFocus?: boolean;
/** Enables the creation of controls from the editor **/
controlsContext?: ControlsContext;
/** Opens the given query in a new Discover tab **/
onOpenQueryInNewTab?: (tabName: string, esqlQuery: string) => Promise<void>;
/** The available ESQL variables from the page context this editor was opened in */
esqlVariables?: ESQLControlVariable[];
/** Resize the editor to fit the initially passed query on mount */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ export const FlyoutContent: FC<FlyoutContentProps> = ({ deps, props }) => {
{dataView ? (
<EuiFlexGroup direction="column" gutterSize="s" css={{ height: '100%' }}>
<EuiFlexItem grow={false}>
<QueryBar />
<QueryBar onOpenIndexInDiscover={props.onOpenIndexInDiscover} />
</EuiFlexItem>

<EuiFlexItem grow={true} css={{ minHeight: 0 }}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,19 +28,20 @@ export const UnsavedChangesModal: React.FC<UnsavedChangesModal> = ({ onClose })

const exitAttemptWithUnsavedFields = useObservable(
indexUpdateService.exitAttemptWithUnsavedChanges$,
false
{ isActive: false }
);

const closeWithoutSaving = () => {
indexUpdateService.discardUnsavedChanges();
onClose();
exitAttemptWithUnsavedFields.onExitCallback?.();
};

const continueEditing = () => {
indexUpdateService.setExitAttemptWithUnsavedChanges(false);
};

if (!exitAttemptWithUnsavedFields) {
if (!exitAttemptWithUnsavedFields.isActive) {
return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import React, { useMemo, useState } from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import {
EuiButton,
EuiFlexGroup,
Expand All @@ -20,9 +20,13 @@ import { useKibana } from '@kbn/kibana-react-plugin/public';
import useObservable from 'react-use/lib/useObservable';
import { FormattedMessage } from '@kbn/i18n-react';
import { FilePicker } from './file_picker';
import type { KibanaContextExtra } from '../types';
import type { EditLookupIndexContentContext, KibanaContextExtra } from '../types';

export const QueryBar = () => {
export const QueryBar = ({
onOpenIndexInDiscover,
}: {
onOpenIndexInDiscover?: EditLookupIndexContentContext['onOpenIndexInDiscover'];
}) => {
const {
services: { share, data, indexUpdateService, indexEditorTelemetryService },
} = useKibana<KibanaContextExtra>();
Expand All @@ -34,13 +38,15 @@ export const QueryBar = () => {
indexUpdateService.indexCreated$,
indexUpdateService.isIndexCreated()
);
const indexName = useObservable(indexUpdateService.indexName$, null);

const [queryError, setQueryError] = useState<string>('');

const discoverLocator = useMemo(() => {
return share?.url.locators.get('DISCOVER_APP_LOCATOR');
}, [share?.url.locators]);

// Only used as fallback if onOpenIndexInDiscover is not provided
const discoverLink =
isIndexCreated && esqlDiscoverQuery
? discoverLocator?.getRedirectUrl({
Expand All @@ -51,6 +57,28 @@ export const QueryBar = () => {
})
: null;

const openInDiscover = useCallback(
(e: React.MouseEvent) => {
indexEditorTelemetryService.trackQueryThisIndexClicked(searchQuery);

// If onOpenIndexInDiscover is provided, we let that handler to manage the navigation to Discover
// If not, the button href will be executed
if (onOpenIndexInDiscover && indexName && esqlDiscoverQuery) {
e.preventDefault();
const onExitCallback = () => onOpenIndexInDiscover(indexName, esqlDiscoverQuery);
indexUpdateService.exit(onExitCallback);
}
},
[
indexEditorTelemetryService,
searchQuery,
onOpenIndexInDiscover,
indexName,
esqlDiscoverQuery,
indexUpdateService,
]
);

if (!dataView) {
return null;
}
Expand Down Expand Up @@ -81,14 +109,15 @@ export const QueryBar = () => {
<FilePicker />
</EuiFlexItem>
<EuiFlexItem grow={false}>
{/* eslint-disable-next-line @elastic/eui/href-or-on-click */}
<EuiButton
size={'s'}
color={'text'}
isDisabled={!discoverLink}
href={discoverLink ?? undefined}
onClick={() => indexEditorTelemetryService.trackQueryThisIndexClicked(searchQuery)}
size="s"
color="text"
isDisabled={!isIndexCreated || !esqlDiscoverQuery}
onClick={openInDiscover}
href={discoverLink || undefined}
target="_blank"
iconType={'discoverApp'}
iconType="discoverApp"
>
<EuiText size="xs">
<FormattedMessage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,11 @@ export class IndexUpdateService {
private readonly _error$ = new BehaviorSubject<IndexEditorError | null>(null);
public readonly error$: Observable<IndexEditorError | null> = this._error$.asObservable();

private readonly _exitAttemptWithUnsavedChanges$ = new BehaviorSubject<boolean>(false);
private readonly _exitAttemptWithUnsavedChanges$ = new BehaviorSubject<{
isActive: boolean;
onExitCallback?: () => void;
}>({ isActive: false });

public readonly exitAttemptWithUnsavedChanges$ =
this._exitAttemptWithUnsavedChanges$.asObservable();

Expand Down Expand Up @@ -965,8 +969,8 @@ export class IndexUpdateService {
this.telemetry.trackEditInteraction({ actionType: 'delete_column' });
}

public setExitAttemptWithUnsavedChanges(value: boolean) {
this._exitAttemptWithUnsavedChanges$.next(value);
public setExitAttemptWithUnsavedChanges(isActive: boolean, onExitCallback?: () => void) {
this._exitAttemptWithUnsavedChanges$.next({ isActive, onExitCallback });
}

public discardUnsavedChanges() {
Expand Down Expand Up @@ -1059,16 +1063,17 @@ export class IndexUpdateService {
return lookupIndexesResult.indices.some((index) => index.name === indexName);
}

public exit() {
public exit(onExitCallback?: () => void) {
const hasUnsavedChanges = this._hasUnsavedChanges$.getValue();
const unsavedColumns = this._pendingColumnsToBeSaved$
.getValue()
.filter((col) => !isPlaceholderColumn(col.name));

if (hasUnsavedChanges || unsavedColumns.length > 0) {
this.setExitAttemptWithUnsavedChanges(true);
this.setExitAttemptWithUnsavedChanges(true, onExitCallback);
} else {
this.destroy();
onExitCallback?.();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export interface EditLookupIndexContentContext {
/** Indicates if new fields have been added to the index */
indexHasNewFields: boolean;
}) => void;
onOpenIndexInDiscover?: (indexName: string, esqlQuery: string) => Promise<void>;
}

export interface EditLookupIndexFlyoutDeps {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,18 @@ export const DiscoverTopNav = ({
onUpdateESQLQuery: stateContainer.actions.updateESQLQuery,
});

const onOpenQueryInNewTab = useCallback(
async (tabName: string, esqlQuery: string) => {
dispatch(
internalStateActions.openInNewTab({
tabLabel: tabName,
appState: { query: { esql: esqlQuery } },
})
);
},
[dispatch]
);

useEffect(() => {
return () => {
// Make sure to close the editors when unmounting
Expand Down Expand Up @@ -316,6 +328,7 @@ export const DiscoverTopNav = ({
}
: undefined
}
onOpenQueryInNewTab={tabsEnabled ? onOpenQueryInNewTab : undefined}
/>
{isESQLToDataViewTransitionModalVisible && (
<ESQLToDataViewTransitionModal onClose={onESQLToDataViewTransitionModalClose} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ export interface QueryBarTopRowProps<QT extends Query | AggregateQuery = Query>
*/
controlsWrapper: React.ReactNode;
};
/**
* Optional ES|QL prop - Callback function invoked to open the given ES|QL query in a new Discover tab
*/
onOpenQueryInNewTab?: ESQLEditorProps['onOpenQueryInNewTab'];
useBackgroundSearchButton?: boolean;
showProjectPicker?: boolean;
}
Expand Down Expand Up @@ -919,6 +923,7 @@ export const QueryBarTopRow = React.memo(
: undefined
}
esqlVariables={props.esqlVariablesConfig?.esqlVariables ?? []}
onOpenQueryInNewTab={props.onOpenQueryInNewTab}
/>
)
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ export function createSearchBar({
esqlEditorInitialState={props.esqlEditorInitialState}
onEsqlEditorInitialStateChange={props.onEsqlEditorInitialStateChange}
esqlVariablesConfig={props.esqlVariablesConfig}
onOpenQueryInNewTab={props.onOpenQueryInNewTab}
useBackgroundSearchButton={props.useBackgroundSearchButton}
/>
</core.i18n.Context>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,9 @@ export interface SearchBarOwnProps<QT extends AggregateQuery | Query = Query> {
*/
esqlVariablesConfig?: QueryBarTopRowProps['esqlVariablesConfig'];

/** Optional configurations for the lookup join index editor */
onOpenQueryInNewTab?: QueryBarTopRowProps['onOpenQueryInNewTab'];

esqlEditorInitialState?: QueryBarTopRowProps['esqlEditorInitialState'];
onEsqlEditorInitialStateChange?: QueryBarTopRowProps['onEsqlEditorInitialStateChange'];

Expand Down Expand Up @@ -782,6 +785,7 @@ export class SearchBarUI<QT extends (Query | AggregateQuery) | Query = Query> ex
esqlEditorInitialState={this.props.esqlEditorInitialState}
onEsqlEditorInitialStateChange={this.props.onEsqlEditorInitialStateChange}
esqlVariablesConfig={this.props.esqlVariablesConfig}
onOpenQueryInNewTab={this.props.onOpenQueryInNewTab}
useBackgroundSearchButton={this.props.useBackgroundSearchButton}
showProjectPicker={this.props.showProjectPicker}
/>
Expand Down