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

[8.x] [ES|QL] Present ES|QL as an equal to data views on the "no data views" screen (#194077) #195684

Merged
merged 1 commit into from
Oct 9, 2024
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 @@ -22,12 +22,14 @@ import { getHasApiKeys$ } from '../lib/get_has_api_keys';
export interface Props {
/** Handler for successfully creating a new data view. */
onDataViewCreated: (dataView: unknown) => void;
/** Handler for when try ES|QL is clicked and user has been navigated to try ES|QL in discover. */
onESQLNavigationComplete?: () => void;
/** if set to true allows creation of an ad-hoc dataview from data view editor */
allowAdHocDataView?: boolean;
/** if the kibana instance is customly branded */
showPlainSpinner: boolean;
/** If the cluster has data, this handler allows the user to try ES|QL */
onTryESQL?: () => void;
/** Handler for when try ES|QL is clicked and user has been navigated to try ES|QL in discover. */
onESQLNavigationComplete?: () => void;
}

type AnalyticsNoDataPageProps = Props &
Expand Down Expand Up @@ -119,9 +121,10 @@ const flavors: {
*/
export const AnalyticsNoDataPage: React.FC<AnalyticsNoDataPageProps> = ({
onDataViewCreated,
onESQLNavigationComplete,
allowAdHocDataView,
showPlainSpinner,
onTryESQL,
onESQLNavigationComplete,
...services
}) => {
const { prependBasePath, kibanaGuideDocLink, getHttp: get, pageFlavor } = services;
Expand All @@ -138,8 +141,9 @@ export const AnalyticsNoDataPage: React.FC<AnalyticsNoDataPageProps> = ({
{...{
noDataConfig,
onDataViewCreated,
onESQLNavigationComplete,
allowAdHocDataView,
onTryESQL,
onESQLNavigationComplete,
showPlainSpinner,
}}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ export default {

export const Analytics = (params: AnalyticsNoDataPageStorybookParams) => {
return (
<AnalyticsNoDataPageProvider {...mock.getServices(params)}>
<Component {...mock.getProps()} />
<AnalyticsNoDataPageProvider {...mock.getProps(params)} {...mock.getServices(params)}>
<Component {...mock.getProps(params)} />
</AnalyticsNoDataPageProvider>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
getAnalyticsNoDataPageServicesMock,
getAnalyticsNoDataPageServicesMockWithCustomBranding,
} from '@kbn/shared-ux-page-analytics-no-data-mocks';
import { NoDataViewsPrompt } from '@kbn/shared-ux-prompt-no-data-views';

import { AnalyticsNoDataPageProvider } from './services';
import { AnalyticsNoDataPage as Component } from './analytics_no_data_page.component';
Expand All @@ -29,28 +30,86 @@ describe('AnalyticsNoDataPage', () => {
jest.resetAllMocks();
});

it('renders correctly', async () => {
const component = mountWithIntl(
<AnalyticsNoDataPageProvider {...services}>
<AnalyticsNoDataPage onDataViewCreated={onDataViewCreated} allowAdHocDataView={true} />
</AnalyticsNoDataPageProvider>
);
describe('loading state', () => {
it('renders correctly', async () => {
const component = mountWithIntl(
<AnalyticsNoDataPageProvider {...services}>
<AnalyticsNoDataPage onDataViewCreated={onDataViewCreated} allowAdHocDataView={true} />
</AnalyticsNoDataPageProvider>
);

await act(() => new Promise(setImmediate));
await act(() => new Promise(setImmediate));

expect(component.find(Component).length).toBe(1);
expect(component.find(Component).props().onDataViewCreated).toBe(onDataViewCreated);
expect(component.find(Component).props().allowAdHocDataView).toBe(true);
expect(component.find(Component).length).toBe(1);
expect(component.find(Component).props().onDataViewCreated).toBe(onDataViewCreated);
expect(component.find(Component).props().allowAdHocDataView).toBe(true);
});

it('passes correct boolean value to showPlainSpinner', async () => {
const component = mountWithIntl(
<AnalyticsNoDataPageProvider {...servicesWithCustomBranding}>
<AnalyticsNoDataPage onDataViewCreated={onDataViewCreated} allowAdHocDataView={true} />
</AnalyticsNoDataPageProvider>
);

await act(async () => {
component.update();
});

expect(component.find(Component).length).toBe(1);
expect(component.find(Component).props().showPlainSpinner).toBe(true);
});
});

it('passes correct boolean value to showPlainSpinner', () => {
const component = mountWithIntl(
<AnalyticsNoDataPageProvider {...servicesWithCustomBranding}>
<AnalyticsNoDataPage onDataViewCreated={onDataViewCreated} allowAdHocDataView={true} />
</AnalyticsNoDataPageProvider>
);
describe('with ES data', () => {
jest.spyOn(services, 'hasESData').mockResolvedValue(true);
jest.spyOn(services, 'hasUserDataView').mockResolvedValue(false);

it('renders the prompt to create a data view', async () => {
const onTryESQL = jest.fn();

await act(async () => {
const component = mountWithIntl(
<AnalyticsNoDataPageProvider {...services}>
<AnalyticsNoDataPage
onDataViewCreated={onDataViewCreated}
allowAdHocDataView={true}
onTryESQL={onTryESQL}
/>
</AnalyticsNoDataPageProvider>
);

await new Promise(setImmediate);
component.update();

expect(component.find(Component).length).toBe(1);
expect(component.find(NoDataViewsPrompt).length).toBe(1);
});
});

it('renders the prompt to create a data view with a custom onTryESQL action', async () => {
const onTryESQL = jest.fn();

await act(async () => {
const component = mountWithIntl(
<AnalyticsNoDataPageProvider {...services}>
<AnalyticsNoDataPage
onDataViewCreated={onDataViewCreated}
allowAdHocDataView={true}
onTryESQL={onTryESQL}
/>
</AnalyticsNoDataPageProvider>
);

await new Promise(setImmediate);
component.update();

const tryESQLLink = component.find('button[data-test-subj="tryESQLLink"]');
expect(tryESQLLink.length).toBe(1);
tryESQLLink.simulate('click');

expect(component.find(Component).length).toBe(1);
expect(component.find(Component).props().showPlainSpinner).toBe(true);
expect(onTryESQL).toHaveBeenCalled();
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ import { AnalyticsNoDataPage as Component } from './analytics_no_data_page.compo
*/
export const AnalyticsNoDataPage = ({
onDataViewCreated,
onESQLNavigationComplete,
allowAdHocDataView,
onTryESQL,
onESQLNavigationComplete,
}: AnalyticsNoDataPageProps) => {
const { customBranding, ...services } = useServices();
const showPlainSpinner = useObservable(customBranding.hasCustomBranding$) ?? false;
Expand All @@ -33,6 +34,7 @@ export const AnalyticsNoDataPage = ({
allowAdHocDataView={allowAdHocDataView}
onDataViewCreated={onDataViewCreated}
onESQLNavigationComplete={onESQLNavigationComplete}
onTryESQL={onTryESQL}
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@kbn/i18n-react",
"@kbn/core-http-browser",
"@kbn/core-http-browser-mocks",
"@kbn/shared-ux-prompt-no-data-views",
],
"exclude": [
"target/**/*",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ import type {
} from '@kbn/shared-ux-page-analytics-no-data-types';
import { of } from 'rxjs';

interface PropArguments {
useCustomOnTryESQL: boolean;
}

type ServiceArguments = Pick<AnalyticsNoDataPageServices, 'kibanaGuideDocLink' | 'customBranding'>;

export type Params = ArgumentParams<{}, ServiceArguments> & KibanaNoDataPageStorybookParams;
export type Params = ArgumentParams<PropArguments, ServiceArguments> &
KibanaNoDataPageStorybookParams;

const kibanaNoDataMock = new KibanaNoDataPageStorybookMock();

Expand All @@ -30,7 +35,13 @@ export class StorybookMock extends AbstractStorybookMock<
{},
ServiceArguments
> {
propArguments = {};
propArguments = {
// requires hasESData to be toggled to true
useCustomOnTryESQL: {
control: 'boolean',
defaultValue: false,
},
};
serviceArguments = {
kibanaGuideDocLink: {
control: 'text',
Expand Down Expand Up @@ -59,9 +70,10 @@ export class StorybookMock extends AbstractStorybookMock<
};
}

getProps() {
getProps(params: Params) {
return {
onDataViewCreated: action('onDataViewCreated'),
onTryESQL: params.useCustomOnTryESQL ? action('onTryESQL-from-props') : undefined,
};
}
}
2 changes: 2 additions & 0 deletions packages/shared-ux/page/analytics_no_data/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ export interface AnalyticsNoDataPageProps {
onDataViewCreated: (dataView: unknown) => void;
/** if set to true allows creation of an ad-hoc data view from data view editor */
allowAdHocDataView?: boolean;
/** If the cluster has data, this handler allows the user to try ES|QL */
onTryESQL?: () => void;
/** Handler for when try ES|QL is clicked and user has been navigated to try ES|QL in discover. */
onESQLNavigationComplete?: () => void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ import { useServices } from './services';
*/
export const KibanaNoDataPage = ({
onDataViewCreated,
onESQLNavigationComplete,
noDataConfig,
allowAdHocDataView,
onTryESQL,
onESQLNavigationComplete,
showPlainSpinner,
}: KibanaNoDataPageProps) => {
// These hooks are temporary, until this component is moved to a package.
Expand Down Expand Up @@ -58,8 +59,9 @@ export const KibanaNoDataPage = ({
return (
<NoDataViewsPrompt
onDataViewCreated={onDataViewCreated}
onESQLNavigationComplete={onESQLNavigationComplete}
allowAdHocDataView={allowAdHocDataView}
onTryESQL={onTryESQL}
onESQLNavigationComplete={onESQLNavigationComplete}
/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/shared-ux/page/kibana_no_data/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ export interface KibanaNoDataPageProps {
allowAdHocDataView?: boolean;
/** Set to true if the kibana is customly branded */
showPlainSpinner: boolean;
/** If the cluster has data, this handler allows the user to try ES|QL */
onTryESQL?: () => void;
/** Handler for when try ES|QL is clicked and user has been navigated to try ES|QL in discover. */
onESQLNavigationComplete?: () => void;
}
76 changes: 0 additions & 76 deletions packages/shared-ux/prompt/no_data_views/impl/src/actions.tsx

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,14 @@ export const DataViewIllustration = () => {
}
`;

return <img src={svg} css={css} alt="Data view illustration" />;
return (
<img
src={svg}
css={css}
alt="Data view illustration"
data-test-subj="DataViewIllustration"
width="110"
height="100"
/>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import { FormattedMessage } from '@kbn/i18n-react';

interface Props {
href: string;
['data-test-subj']?: string;
}

export function DocumentationLink({ href }: Props) {
export function DocumentationLink({ href, ['data-test-subj']: dataTestSubj }: Props) {
return (
<dl>
<EuiTitle size="xxs">
Expand All @@ -28,7 +29,7 @@ export function DocumentationLink({ href }: Props) {
</EuiTitle>
&emsp;
<dd className="eui-displayInline">
<EuiLink href={href} target="_blank" external>
<EuiLink href={href} target="_blank" data-test-subj={dataTestSubj} external>
<FormattedMessage
id="sharedUXPackages.noDataViewsPrompt.readDocumentation"
defaultMessage="Read the docs"
Expand Down
Loading