From 709f9b1de9f3d7460842207242508d4de43ad351 Mon Sep 17 00:00:00 2001 From: Tim Sullivan Date: Wed, 9 Oct 2024 14:44:30 -0700 Subject: [PATCH] [ES|QL] Present ES|QL as an equal to data views on the "no data views" screen (#194077) ## Summary Resolves https://github.com/elastic/kibana/issues/176291 ### Screenshots #### Discover/Dashboard/Visualize image #### Stack Management > Data view image #### If User does not have privilege to create a Data View image ### Checklist Delete any items that are not applicable to this PR. - [x] Use a new SVG resource for the ES|QL illustration - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [ ] [Flaky Test Runner](https://ci-stats.kibana.dev/trigger_flaky_test_runner/1) was used on any tests changed - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [ ] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers) --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Liam Thompson <32779855+leemthompo@users.noreply.github.com> Co-authored-by: Andrea Del Rio (cherry picked from commit 56e1e68b307bc62445f04ae6f443f4854a308547) --- .../src/analytics_no_data_page.component.tsx | 12 +- .../src/analytics_no_data_page.stories.tsx | 4 +- .../impl/src/analytics_no_data_page.test.tsx | 95 +- .../impl/src/analytics_no_data_page.tsx | 4 +- .../page/analytics_no_data/impl/tsconfig.json | 1 + .../analytics_no_data/mocks/src/storybook.ts | 18 +- .../page/analytics_no_data/types/index.d.ts | 2 + .../impl/src/kibana_no_data_page.tsx | 6 +- .../page/kibana_no_data/types/index.d.ts | 2 + .../prompt/no_data_views/impl/src/actions.tsx | 76 - .../impl/src/data_view_illustration.tsx | 11 +- .../impl/src/documentation_link.tsx | 5 +- .../impl/src/esql_illustration.svg | 1600 +++++++++++++++++ .../impl/src/esql_illustration.tsx | 24 + .../impl/src/no_data_views.component.test.tsx | 50 +- .../impl/src/no_data_views.component.tsx | 261 ++- .../no_data_views/impl/src/no_data_views.tsx | 7 +- .../prompt/no_data_views/impl/tsconfig.json | 2 - .../no_data_views/mocks/src/storybook.ts | 14 +- .../prompt/no_data_views/types/index.d.ts | 8 +- src/plugins/data_view_management/kibana.jsonc | 1 + .../index_pattern_table.tsx | 11 +- .../mount_management_section.tsx | 44 +- .../data_view_management/public/plugin.ts | 2 + .../data_view_management/public/types.ts | 2 + .../data_view_management/tsconfig.json | 1 + .../group6/dashboard_esql_no_data.ts | 33 + .../functional/apps/dashboard/group6/index.ts | 1 + .../apps/management/data_views/_try_esql.ts | 34 + test/functional/apps/management/index.ts | 1 + test/functional/page_objects/discover_page.ts | 6 + test/functional/services/esql.ts | 7 + .../translations/translations/fr-FR.json | 5 - .../translations/translations/ja-JP.json | 5 - .../translations/translations/zh-CN.json | 5 - .../data_views/feature_controls/security.ts | 6 +- 36 files changed, 2132 insertions(+), 234 deletions(-) delete mode 100644 packages/shared-ux/prompt/no_data_views/impl/src/actions.tsx create mode 100644 packages/shared-ux/prompt/no_data_views/impl/src/esql_illustration.svg create mode 100644 packages/shared-ux/prompt/no_data_views/impl/src/esql_illustration.tsx create mode 100644 test/functional/apps/dashboard/group6/dashboard_esql_no_data.ts create mode 100644 test/functional/apps/management/data_views/_try_esql.ts diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx index 41c525c5ca0b0..16d1bebd46548 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.component.tsx @@ -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 & @@ -119,9 +121,10 @@ const flavors: { */ export const AnalyticsNoDataPage: React.FC = ({ onDataViewCreated, - onESQLNavigationComplete, allowAdHocDataView, showPlainSpinner, + onTryESQL, + onESQLNavigationComplete, ...services }) => { const { prependBasePath, kibanaGuideDocLink, getHttp: get, pageFlavor } = services; @@ -138,8 +141,9 @@ export const AnalyticsNoDataPage: React.FC = ({ {...{ noDataConfig, onDataViewCreated, - onESQLNavigationComplete, allowAdHocDataView, + onTryESQL, + onESQLNavigationComplete, showPlainSpinner, }} /> diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.stories.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.stories.tsx index 3c75cefb38cb2..fa251cb03bdbe 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.stories.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.stories.tsx @@ -29,8 +29,8 @@ export default { export const Analytics = (params: AnalyticsNoDataPageStorybookParams) => { return ( - - + + ); }; diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx index 543c1c4817c5b..6b2d3441ed0d1 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.test.tsx @@ -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'; @@ -29,28 +30,86 @@ describe('AnalyticsNoDataPage', () => { jest.resetAllMocks(); }); - it('renders correctly', async () => { - const component = mountWithIntl( - - - - ); + describe('loading state', () => { + it('renders correctly', async () => { + const component = mountWithIntl( + + + + ); - 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( + + + + ); + + 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( - - - - ); + 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( + + + + ); + + 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( + + + + ); + + 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(); + }); + }); }); }); diff --git a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx index b64a296bbf74a..f7c80705daa58 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx +++ b/packages/shared-ux/page/analytics_no_data/impl/src/analytics_no_data_page.tsx @@ -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; @@ -33,6 +34,7 @@ export const AnalyticsNoDataPage = ({ allowAdHocDataView={allowAdHocDataView} onDataViewCreated={onDataViewCreated} onESQLNavigationComplete={onESQLNavigationComplete} + onTryESQL={onTryESQL} /> ); }; diff --git a/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json b/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json index 659aacfd3874d..ba872e1ecd761 100644 --- a/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json +++ b/packages/shared-ux/page/analytics_no_data/impl/tsconfig.json @@ -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/**/*", diff --git a/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts b/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts index c664bb192518c..f8cca693a072c 100644 --- a/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts +++ b/packages/shared-ux/page/analytics_no_data/mocks/src/storybook.ts @@ -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; -export type Params = ArgumentParams<{}, ServiceArguments> & KibanaNoDataPageStorybookParams; +export type Params = ArgumentParams & + KibanaNoDataPageStorybookParams; const kibanaNoDataMock = new KibanaNoDataPageStorybookMock(); @@ -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', @@ -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, }; } } diff --git a/packages/shared-ux/page/analytics_no_data/types/index.d.ts b/packages/shared-ux/page/analytics_no_data/types/index.d.ts index 9fd6653a48b6a..94bf85500da6b 100644 --- a/packages/shared-ux/page/analytics_no_data/types/index.d.ts +++ b/packages/shared-ux/page/analytics_no_data/types/index.d.ts @@ -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; } diff --git a/packages/shared-ux/page/kibana_no_data/impl/src/kibana_no_data_page.tsx b/packages/shared-ux/page/kibana_no_data/impl/src/kibana_no_data_page.tsx index 2042d7fa1420d..d74c3aabd5662 100644 --- a/packages/shared-ux/page/kibana_no_data/impl/src/kibana_no_data_page.tsx +++ b/packages/shared-ux/page/kibana_no_data/impl/src/kibana_no_data_page.tsx @@ -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. @@ -58,8 +59,9 @@ export const KibanaNoDataPage = ({ return ( ); } diff --git a/packages/shared-ux/page/kibana_no_data/types/index.d.ts b/packages/shared-ux/page/kibana_no_data/types/index.d.ts index 56067e9d555f9..c391149f7efaa 100644 --- a/packages/shared-ux/page/kibana_no_data/types/index.d.ts +++ b/packages/shared-ux/page/kibana_no_data/types/index.d.ts @@ -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; } diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/actions.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/actions.tsx deleted file mode 100644 index 6f2af97df6e04..0000000000000 --- a/packages/shared-ux/prompt/no_data_views/impl/src/actions.tsx +++ /dev/null @@ -1,76 +0,0 @@ -/* - * 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 { EuiButton, EuiLink, EuiSpacer, EuiText } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import React from 'react'; - -interface NoDataButtonProps { - onClickCreate: (() => void) | undefined; - canCreateNewDataView: boolean; - onTryESQL?: () => void; - esqlDocLink?: string; -} - -const createDataViewText = i18n.translate('sharedUXPackages.noDataViewsPrompt.addDataViewText', { - defaultMessage: 'Create data view', -}); - -export const NoDataButtonLink = ({ - onClickCreate, - canCreateNewDataView, - onTryESQL, - esqlDocLink, -}: NoDataButtonProps) => { - if (!onTryESQL && !canCreateNewDataView) { - return null; - } - - return ( - <> - {canCreateNewDataView && ( - - {createDataViewText} - - )} - {canCreateNewDataView && onTryESQL && } - {onTryESQL && ( - - - - - ), - }} - /> - - - - - - )} - - ); -}; diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/data_view_illustration.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/data_view_illustration.tsx index cb817225254a9..099cdc87a21eb 100644 --- a/packages/shared-ux/prompt/no_data_views/impl/src/data_view_illustration.tsx +++ b/packages/shared-ux/prompt/no_data_views/impl/src/data_view_illustration.tsx @@ -26,5 +26,14 @@ export const DataViewIllustration = () => { } `; - return Data view illustration; + return ( + Data view illustration + ); }; diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/documentation_link.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/documentation_link.tsx index 8e74bead6922e..d190764af947d 100644 --- a/packages/shared-ux/prompt/no_data_views/impl/src/documentation_link.tsx +++ b/packages/shared-ux/prompt/no_data_views/impl/src/documentation_link.tsx @@ -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 (
@@ -28,7 +29,7 @@ export function DocumentationLink({ href }: Props) {
- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/esql_illustration.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/esql_illustration.tsx new file mode 100644 index 0000000000000..a2da4c416ed55 --- /dev/null +++ b/packages/shared-ux/prompt/no_data_views/impl/src/esql_illustration.tsx @@ -0,0 +1,24 @@ +/* + * 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 React from 'react'; + +import png from './esql_illustration.svg'; + +export const EsqlIllustration = () => { + return ( + ES|QL illustration + ); +}; diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.test.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.test.tsx index ad2e176a511f0..75363c80b67b5 100644 --- a/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.test.tsx +++ b/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.test.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { mountWithIntl } from '@kbn/test-jest-helpers'; -import { EuiButton, EuiEmptyPrompt } from '@elastic/eui'; +import { EuiButton, EuiCard } from '@elastic/eui'; import { NoDataViewsPrompt } from './no_data_views.component'; import { DocumentationLink } from './documentation_link'; @@ -19,36 +19,64 @@ describe('', () => { ); - expect(component.find(EuiEmptyPrompt).length).toBe(1); - expect(component.find(EuiButton).length).toBe(1); - expect(component.find(DocumentationLink).length).toBe(1); + expect(component.find(EuiCard).length).toBe(2); + expect(component.find(EuiButton).length).toBe(2); + expect(component.find(DocumentationLink).length).toBe(2); + + expect(component.find('EuiButton[data-test-subj="createDataViewButton"]').length).toBe(1); + expect(component.find('DocumentationLink[data-test-subj="docLinkDataViews"]').length).toBe(1); + + expect(component.find('EuiButton[data-test-subj="tryESQLLink"]').length).toBe(1); + expect(component.find('DocumentationLink[data-test-subj="docLinkEsql"]').length).toBe(1); }); - test('does not render button if canCreateNewDataViews is false', () => { + test('does not render "Create data view" button if canCreateNewDataViews is false', () => { const component = mountWithIntl(); - expect(component.find(EuiButton).length).toBe(0); + expect(component.find('EuiButton[data-test-subj="createDataViewButton"]').length).toBe(0); }); - test('does not documentation link if linkToDocumentation is not provided', () => { + test('does not render documentation links if links to documentation are not provided', () => { const component = mountWithIntl( ); - expect(component.find(DocumentationLink).length).toBe(0); + expect(component.find('DocumentationLink[data-test-subj="docLinkDataViews"]').length).toBe(0); + expect(component.find('DocumentationLink[data-test-subj="docLinkEsql"]').length).toBe(0); }); test('onClickCreate', () => { const onClickCreate = jest.fn(); const component = mountWithIntl( - + ); - component.find('button').simulate('click'); + component.find('button[data-test-subj="createDataViewButton"]').simulate('click'); expect(onClickCreate).toHaveBeenCalledTimes(1); }); + + test('onClickTryEsql', () => { + const onClickTryEsql = jest.fn(); + const component = mountWithIntl( + + ); + + component.find('button[data-test-subj="tryESQLLink"]').simulate('click'); + + expect(onClickTryEsql).toHaveBeenCalledTimes(1); + }); }); diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.tsx index d5807891e734d..3bfed37aa0b1a 100644 --- a/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.tsx +++ b/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.component.tsx @@ -7,95 +7,222 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ -import React from 'react'; import { css } from '@emotion/react'; +import React from 'react'; -import { EuiEmptyPrompt, EuiPanel } from '@elastic/eui'; +import { + EuiButton, + EuiCard, + EuiFlexGroup, + EuiFlexItem, + EuiHorizontalRule, + EuiSpacer, + EuiText, + EuiTextAlign, + EuiToolTip, + useEuiPaddingCSS, +} from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; -import { withSuspense } from '@kbn/shared-ux-utility'; import { NoDataViewsPromptComponentProps } from '@kbn/shared-ux-prompt-no-data-views-types'; import { DocumentationLink } from './documentation_link'; -import { NoDataButtonLink } from './actions'; +import { DataViewIllustration } from './data_view_illustration'; +import { EsqlIllustration } from './esql_illustration'; -// Using raw value because it is content dependent -const MAX_WIDTH = 830; +// max width value to use in pixels +const MAX_WIDTH = 770; -/** - * A presentational component that is shown in cases when there are no data views created yet. - */ -export const NoDataViewsPrompt = ({ +const PromptAddDataViews = ({ onClickCreate, canCreateNewDataView, dataViewsDocLink, + emptyPromptColor, +}: Pick< + NoDataViewsPromptComponentProps, + 'onClickCreate' | 'canCreateNewDataView' | 'dataViewsDocLink' | 'emptyPromptColor' +>) => { + const icon = ; + + const title = ( + + ); + + const description = ( + <> + {canCreateNewDataView ? ( + + ) : ( + + )} + + ); + + const footer = dataViewsDocLink ? ( + <> + {canCreateNewDataView ? ( + + + + ) : ( + + } + > + + + + + )} + + + + ) : undefined; + + return ( + + ); +}; + +const PromptTryEsql = ({ onTryESQL, esqlDocLink, - emptyPromptColor = 'plain', -}: NoDataViewsPromptComponentProps) => { - const title = canCreateNewDataView ? ( -

- -
- -

- ) : ( -

- -

- ); + emptyPromptColor, +}: Pick< + NoDataViewsPromptComponentProps, + 'onClickCreate' | 'onTryESQL' | 'esqlDocLink' | 'emptyPromptColor' +>) => { + if (!onTryESQL) { + // we need to handle the case where the Try ES|QL click handler is not set because + // onTryESQL is set via a useEffect that has asynchronous dependencies + return null; + } + + const icon = ; - const body = canCreateNewDataView ? ( -

- -

- ) : ( -

- -

+ const title = ( + ); - const footer = dataViewsDocLink ? : undefined; + const description = ( + + ); - // Load this illustration lazily - const Illustration = withSuspense( - React.lazy(() => - import('./data_view_illustration').then(({ DataViewIllustration }) => { - return { default: DataViewIllustration }; - }) - ), - + const footer = ( + <> + + + + + {esqlDocLink && } + ); - const icon = ; - const actions = ( - + return ( + ); +}; + +/** + * A presentational component that is shown in cases when there are no data views created yet. + */ +export const NoDataViewsPrompt = ({ + onClickCreate, + canCreateNewDataView, + dataViewsDocLink, + onTryESQL, + esqlDocLink, + emptyPromptColor = 'plain', +}: NoDataViewsPromptComponentProps) => { + const cssStyles = [ + css` + max-width: ${MAX_WIDTH}px; + `, + useEuiPaddingCSS('top').m, + useEuiPaddingCSS('right').m, + useEuiPaddingCSS('left').m, + ]; return ( - + > + + + +

+ +

+
+
+ + + + + + + + + + + +
+ ); }; diff --git a/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.tsx b/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.tsx index 43ae5f267ea90..340147505cb25 100644 --- a/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.tsx +++ b/packages/shared-ux/prompt/no_data_views/impl/src/no_data_views.tsx @@ -27,12 +27,15 @@ type CloseDataViewEditorFn = ReturnType { - const { canCreateNewDataView, openDataViewEditor, dataViewsDocLink, onTryESQL, esqlDocLink } = + const { canCreateNewDataView, openDataViewEditor, dataViewsDocLink, esqlDocLink, ...services } = useServices(); + const onTryESQL = onTryESQLProp ?? services.onTryESQL; + const closeDataViewEditor = useRef(); useEffect(() => { diff --git a/packages/shared-ux/prompt/no_data_views/impl/tsconfig.json b/packages/shared-ux/prompt/no_data_views/impl/tsconfig.json index 673823e620474..2af357080c07c 100644 --- a/packages/shared-ux/prompt/no_data_views/impl/tsconfig.json +++ b/packages/shared-ux/prompt/no_data_views/impl/tsconfig.json @@ -16,8 +16,6 @@ ], "kbn_references": [ "@kbn/i18n-react", - "@kbn/i18n", - "@kbn/shared-ux-utility", "@kbn/test-jest-helpers", "@kbn/shared-ux-prompt-no-data-views-types", "@kbn/shared-ux-prompt-no-data-views-mocks", diff --git a/packages/shared-ux/prompt/no_data_views/mocks/src/storybook.ts b/packages/shared-ux/prompt/no_data_views/mocks/src/storybook.ts index 63f46d2008077..973152201587d 100644 --- a/packages/shared-ux/prompt/no_data_views/mocks/src/storybook.ts +++ b/packages/shared-ux/prompt/no_data_views/mocks/src/storybook.ts @@ -34,17 +34,19 @@ export class StorybookMock extends AbstractStorybookMock< defaultValue: true, }, dataViewsDocLink: { - options: ['some/link', undefined], - control: { type: 'radio' }, - }, - esqlDocLink: { - options: ['some/link', undefined], + options: ['dataviews/link', undefined], control: { type: 'radio' }, + defaultValue: 'dataviews/link', }, canTryEsql: { control: 'boolean', defaultValue: true, }, + esqlDocLink: { + options: ['esql/link', undefined], + control: { type: 'radio' }, + defaultValue: 'esql/link', + }, }; dependencies = []; @@ -59,7 +61,7 @@ export class StorybookMock extends AbstractStorybookMock< let onTryESQL; if (canTryEsql !== false) { - onTryESQL = action('onTryESQL'); + onTryESQL = action('onTryESQL-from-services'); } return { diff --git a/packages/shared-ux/prompt/no_data_views/types/index.d.ts b/packages/shared-ux/prompt/no_data_views/types/index.d.ts index 15f9f53c59fe6..7bca285bee717 100644 --- a/packages/shared-ux/prompt/no_data_views/types/index.d.ts +++ b/packages/shared-ux/prompt/no_data_views/types/index.d.ts @@ -42,7 +42,7 @@ export interface NoDataViewsPromptServices { openDataViewEditor: (options: DataViewEditorOptions) => () => void; /** A link to information about Data Views in Kibana */ dataViewsDocLink: string; - /** Get a handler for trying ES|QL */ + /** If the cluster has data, this handler allows the user to try ES|QL */ onTryESQL: (() => void) | undefined; /** A link to the documentation for ES|QL */ esqlDocLink: string; @@ -92,7 +92,7 @@ export interface NoDataViewsPromptComponentProps { emptyPromptColor?: EuiEmptyPromptProps['color']; /** Click handler for create button. **/ onClickCreate?: () => void; - /** Handler for someone wanting to try ES|QL. */ + /** If the cluster has data, this handler allows the user to try ES|QL */ onTryESQL?: () => void; /** Link to documentation on ES|QL. */ esqlDocLink?: string; @@ -104,6 +104,10 @@ export interface NoDataViewsPromptProps { allowAdHocDataView?: boolean; /** Handler for successfully creating a new data view. */ onDataViewCreated: (dataView: unknown) => void; + /** 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; + /** Empty prompt color **/ + emptyPromptColor?: PanelColor; } diff --git a/src/plugins/data_view_management/kibana.jsonc b/src/plugins/data_view_management/kibana.jsonc index 479e357804140..5b827868ee1e8 100644 --- a/src/plugins/data_view_management/kibana.jsonc +++ b/src/plugins/data_view_management/kibana.jsonc @@ -20,6 +20,7 @@ ], "optionalPlugins": [ "noDataPage", + "share", "spaces" ], "requiredBundles": [ diff --git a/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx b/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx index cb93e01d1cc15..4512cb520c574 100644 --- a/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx +++ b/src/plugins/data_view_management/public/components/index_pattern_table/index_pattern_table.tsx @@ -26,7 +26,7 @@ import { RouteComponentProps, useLocation, withRouter } from 'react-router-dom'; import useObservable from 'react-use/lib/useObservable'; import { reactRouterNavigate, useKibana } from '@kbn/kibana-react-plugin/public'; -import { NoDataViewsPromptComponent } from '@kbn/shared-ux-prompt-no-data-views'; +import { NoDataViewsPromptComponent, useOnTryESQL } from '@kbn/shared-ux-prompt-no-data-views'; import type { SpacesContextProps } from '@kbn/spaces-plugin/public'; import { DataViewType } from '@kbn/data-views-plugin/public'; import { RollupDeprecationTooltip } from '@kbn/rollup'; @@ -86,6 +86,7 @@ export const IndexPatternTable = ({ application, chrome, dataViews, + share, IndexPatternEditor, spaces, overlays, @@ -116,6 +117,12 @@ export const IndexPatternTable = ({ const hasDataView = useObservable(dataViewController.hasDataView$, defaults.hasDataView); const hasESData = useObservable(dataViewController.hasESData$, defaults.hasEsData); + const useOnTryESQLParams = { + locatorClient: share?.url.locators, + navigateToApp: application.navigateToApp, + }; + const onTryESQL = useOnTryESQL(useOnTryESQLParams); + const handleOnChange = ({ queryText, error }: { queryText: string; error: unknown }) => { if (!error) { setQuery(queryText); @@ -370,6 +377,8 @@ export const IndexPatternTable = ({ onClickCreate={() => setShowCreateDialog(true)} canCreateNewDataView={application.capabilities.indexPatterns.save as boolean} dataViewsDocLink={docLinks.links.indexPatterns.introduction} + onTryESQL={onTryESQL} + esqlDocLink={docLinks.links.query.queryESQL} emptyPromptColor={'subdued'} /> diff --git a/src/plugins/data_view_management/public/management_app/mount_management_section.tsx b/src/plugins/data_view_management/public/management_app/mount_management_section.tsx index 995d5ed977ed3..96e5ae6c96b0c 100644 --- a/src/plugins/data_view_management/public/management_app/mount_management_section.tsx +++ b/src/plugins/data_view_management/public/management_app/mount_management_section.tsx @@ -17,6 +17,7 @@ import { StartServicesAccessor } from '@kbn/core/public'; import { KibanaRenderContextProvider } from '@kbn/react-kibana-context-render'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { ManagementAppMountParams } from '@kbn/management-plugin/public'; +import { NoDataViewsPromptKibanaProvider } from '@kbn/shared-ux-prompt-no-data-views'; import { IndexPatternTableWithRouter, EditIndexPatternContainer, @@ -64,11 +65,13 @@ export async function mountManagementSection( dataViews, fieldFormats, unifiedSearch, + share, spaces, savedObjectsManagement, }, indexPatternManagementStart, ] = await getStartServices(); + const canSave = dataViews.getCanSaveSync(); if (!canSave) { @@ -89,6 +92,7 @@ export async function mountManagementSection( chrome, uiSettings, settings, + share, notifications, overlays, unifiedSearch, @@ -115,23 +119,29 @@ export async function mountManagementSection( ReactDOM.render( - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + , params.element diff --git a/src/plugins/data_view_management/public/plugin.ts b/src/plugins/data_view_management/public/plugin.ts index 77e8c12a13ad0..0d03dc8896fd1 100644 --- a/src/plugins/data_view_management/public/plugin.ts +++ b/src/plugins/data_view_management/public/plugin.ts @@ -21,6 +21,7 @@ import { ManagementSetup } from '@kbn/management-plugin/public'; import { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import { SharePluginStart } from '@kbn/share-plugin/public'; export interface IndexPatternManagementSetupDependencies { management: ManagementSetup; @@ -34,6 +35,7 @@ export interface IndexPatternManagementStartDependencies { dataViewEditor: DataViewEditorStart; dataViews: DataViewsPublicPluginStart; fieldFormats: FieldFormatsStart; + share?: SharePluginStart; spaces?: SpacesPluginStart; unifiedSearch: UnifiedSearchPublicPluginStart; savedObjectsManagement: SavedObjectsManagementPluginStart; diff --git a/src/plugins/data_view_management/public/types.ts b/src/plugins/data_view_management/public/types.ts index b7a9279de8001..161ee3b1e21de 100644 --- a/src/plugins/data_view_management/public/types.ts +++ b/src/plugins/data_view_management/public/types.ts @@ -29,6 +29,7 @@ import type { SpacesPluginStart } from '@kbn/spaces-plugin/public'; import type { SavedObjectsManagementPluginStart } from '@kbn/saved-objects-management-plugin/public'; import type { SettingsStart } from '@kbn/core-ui-settings-browser'; import type { NoDataPagePluginSetup } from '@kbn/no-data-page-plugin/public'; +import { SharePluginStart } from '@kbn/share-plugin/public'; import type { IndexPatternManagementStart } from '.'; import type { DataViewMgmtService } from './management_app/data_view_management_service'; @@ -53,6 +54,7 @@ export interface IndexPatternManagmentContext extends StartServices { fieldFormatEditors: IndexPatternFieldEditorStart['fieldFormatEditors']; IndexPatternEditor: DataViewEditorStart['IndexPatternEditorComponent']; fieldFormats: FieldFormatsStart; + share?: SharePluginStart; spaces?: SpacesPluginStart; savedObjectsManagement: SavedObjectsManagementPluginStart; noDataPage?: NoDataPagePluginSetup; diff --git a/src/plugins/data_view_management/tsconfig.json b/src/plugins/data_view_management/tsconfig.json index ea0c96cc66b74..9857dd44829fa 100644 --- a/src/plugins/data_view_management/tsconfig.json +++ b/src/plugins/data_view_management/tsconfig.json @@ -45,6 +45,7 @@ "@kbn/code-editor", "@kbn/react-kibana-mount", "@kbn/rollup", + "@kbn/share-plugin", ], "exclude": [ "target/**/*", diff --git a/test/functional/apps/dashboard/group6/dashboard_esql_no_data.ts b/test/functional/apps/dashboard/group6/dashboard_esql_no_data.ts new file mode 100644 index 0000000000000..148cb95a82b11 --- /dev/null +++ b/test/functional/apps/dashboard/group6/dashboard_esql_no_data.ts @@ -0,0 +1,33 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const testSubjects = getService('testSubjects'); + const esql = getService('esql'); + const PageObjects = getPageObjects(['discover', 'dashboard']); + + describe('No Data Views: Try ES|QL', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + it('enables user to create a dashboard with ES|QL from no-data-prompt', async () => { + await PageObjects.dashboard.navigateToApp(); + + await testSubjects.existOrFail('noDataViewsPrompt'); + await testSubjects.click('tryESQLLink'); + + await PageObjects.discover.expectOnDiscover(); + await esql.expectEsqlStatement('FROM logs* | LIMIT 10'); + }); + }); +} diff --git a/test/functional/apps/dashboard/group6/index.ts b/test/functional/apps/dashboard/group6/index.ts index 302ca2e0480a0..340c9b425571b 100644 --- a/test/functional/apps/dashboard/group6/index.ts +++ b/test/functional/apps/dashboard/group6/index.ts @@ -37,5 +37,6 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./dashboard_snapshots')); loadTestFile(require.resolve('./embeddable_library')); loadTestFile(require.resolve('./dashboard_esql_chart')); + loadTestFile(require.resolve('./dashboard_esql_no_data')); }); } diff --git a/test/functional/apps/management/data_views/_try_esql.ts b/test/functional/apps/management/data_views/_try_esql.ts new file mode 100644 index 0000000000000..276e61c4a721f --- /dev/null +++ b/test/functional/apps/management/data_views/_try_esql.ts @@ -0,0 +1,34 @@ +/* + * 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 { FtrProviderContext } from '../../../ftr_provider_context'; + +export default function ({ getService, getPageObjects }: FtrProviderContext) { + const kibanaServer = getService('kibanaServer'); + const testSubjects = getService('testSubjects'); + const esql = getService('esql'); + const PageObjects = getPageObjects(['settings', 'common', 'discover']); + + describe('No Data Views: Try ES|QL', () => { + before(async () => { + await kibanaServer.savedObjects.cleanStandardList(); + }); + + it('navigates to Discover and presents an ES|QL query', async () => { + await PageObjects.settings.navigateTo(); + await PageObjects.settings.clickKibanaIndexPatterns(); + + await testSubjects.existOrFail('noDataViewsPrompt'); + await testSubjects.click('tryESQLLink'); + + await PageObjects.discover.expectOnDiscover(); + await esql.expectEsqlStatement('FROM logs* | LIMIT 10'); + }); + }); +} diff --git a/test/functional/apps/management/index.ts b/test/functional/apps/management/index.ts index f3d26f2e1c6d7..2300543f06d51 100644 --- a/test/functional/apps/management/index.ts +++ b/test/functional/apps/management/index.ts @@ -38,6 +38,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) { loadTestFile(require.resolve('./data_views/_legacy_url_redirect')); loadTestFile(require.resolve('./data_views/_exclude_index_pattern')); loadTestFile(require.resolve('./data_views/_index_pattern_filter')); + loadTestFile(require.resolve('./data_views/_try_esql')); loadTestFile(require.resolve('./data_views/_scripted_fields_filter')); loadTestFile(require.resolve('./_import_objects')); loadTestFile(require.resolve('./data_views/_test_huge_fields')); diff --git a/test/functional/page_objects/discover_page.ts b/test/functional/page_objects/discover_page.ts index 1474e9d315538..ab6356075fd81 100644 --- a/test/functional/page_objects/discover_page.ts +++ b/test/functional/page_objects/discover_page.ts @@ -32,6 +32,12 @@ export class DiscoverPageObject extends FtrService { private readonly defaultFindTimeout = this.config.get('timeouts.find'); + /** Ensures that navigation to discover has completed */ + public async expectOnDiscover() { + await this.testSubjects.existOrFail('discoverNewButton'); + await this.testSubjects.existOrFail('discoverOpenButton'); + } + public async getChartTimespan() { return await this.testSubjects.getAttribute('unifiedHistogramChart', 'data-time-range'); } diff --git a/test/functional/services/esql.ts b/test/functional/services/esql.ts index 63836d2c5d2f5..c144c6e8993be 100644 --- a/test/functional/services/esql.ts +++ b/test/functional/services/esql.ts @@ -7,12 +7,19 @@ * License v3.0 only", or the "Server Side Public License, v 1". */ +import expect from '@kbn/expect'; import { FtrService } from '../ftr_provider_context'; export class ESQLService extends FtrService { private readonly retry = this.ctx.getService('retry'); private readonly testSubjects = this.ctx.getService('testSubjects'); + /** Ensures that the ES|QL code editor is loaded with a given statement */ + public async expectEsqlStatement(statement: string) { + const codeEditor = await this.testSubjects.find('ESQLEditor'); + expect(await codeEditor.getAttribute('innerText')).to.contain(statement); + } + public async getHistoryItems(): Promise { const queryHistory = await this.testSubjects.find('ESQLEditor-queryHistory'); const tableBody = await this.retry.try(async () => queryHistory.findByTagName('tbody')); diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index 8cc1a3c11c7a0..780f99ef17239 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -7274,9 +7274,6 @@ "sharedUXPackages.fileUpload.uploadCompleteButtonLabel": "Chargement terminé", "sharedUXPackages.fileUpload.uploadDoneToolTipContent": "Votre fichier a bien été chargé !", "sharedUXPackages.fileUpload.uploadingButtonLabel": "Chargement", - "sharedUXPackages.no_data_views.esqlButtonLabel": "Langue : ES|QL", - "sharedUXPackages.no_data_views.esqlDocsLink": "En savoir plus.", - "sharedUXPackages.no_data_views.esqlMessage": "Vous pouvez aussi rechercher vos données en utilisant directement ES|QL. {docsLink}", "sharedUXPackages.noDataConfig.addIntegrationsDescription": "Utilisez Elastic Agent pour collecter des données et créer des solutions Analytics.", "sharedUXPackages.noDataConfig.addIntegrationsTitle": "Ajouter des intégrations", "sharedUXPackages.noDataConfig.analytics": "Analyse", @@ -7298,8 +7295,6 @@ "sharedUXPackages.noDataViewsPrompt.dataViewExplanation": "Les vues de données identifient les données Elasticsearch que vous souhaitez explorer. Vous pouvez faire pointer des vues de données vers un ou plusieurs flux de données, index et alias d'index, tels que vos données de log d'hier, ou vers tous les index contenant vos données de log.", "sharedUXPackages.noDataViewsPrompt.learnMore": "Envie d'en savoir plus ?", "sharedUXPackages.noDataViewsPrompt.noPermission.dataViewExplanation": "Les vues de données identifient les données Elasticsearch que vous souhaitez explorer. Pour créer des vues de données, demandez les autorisations requises à votre administrateur.", - "sharedUXPackages.noDataViewsPrompt.noPermission.title": "Vous devez disposer d'une autorisation pour pouvoir créer des vues de données", - "sharedUXPackages.noDataViewsPrompt.nowCreate": "Créez à présent une vue de données.", "sharedUXPackages.noDataViewsPrompt.readDocumentation": "Lisez les documents", "sharedUXPackages.noDataViewsPrompt.youHaveData": "Vous avez des données dans Elasticsearch.", "sharedUXPackages.prompt.errors.notFound.body": "Désolé, la page que vous recherchez est introuvable. Elle a peut-être été retirée ou renommée, ou peut-être qu'elle n'a jamais existé.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index a9337cc088189..7018510bce318 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -7028,9 +7028,6 @@ "sharedUXPackages.fileUpload.uploadCompleteButtonLabel": "アップロード完了", "sharedUXPackages.fileUpload.uploadDoneToolTipContent": "ファイルは正常にアップロードされました。", "sharedUXPackages.fileUpload.uploadingButtonLabel": "アップロード中", - "sharedUXPackages.no_data_views.esqlButtonLabel": "言語:ES|QL", - "sharedUXPackages.no_data_views.esqlDocsLink": "詳細情報", - "sharedUXPackages.no_data_views.esqlMessage": "あるいは、直接ES|QLを使用してデータをクエリできます。{docsLink}", "sharedUXPackages.noDataConfig.addIntegrationsDescription": "Elasticエージェントを使用して、データを収集し、分析ソリューションを構築します。", "sharedUXPackages.noDataConfig.addIntegrationsTitle": "統合の追加", "sharedUXPackages.noDataConfig.analytics": "分析", @@ -7052,8 +7049,6 @@ "sharedUXPackages.noDataViewsPrompt.dataViewExplanation": "データビューは、探索するElasticsearchデータを特定します。昨日からのログデータ、ログデータを含むすべてのインデックスなど、1つ以上のデータストリーム、インデックス、インデックスエイリアスをデータビューで参照できます。", "sharedUXPackages.noDataViewsPrompt.learnMore": "詳細について", "sharedUXPackages.noDataViewsPrompt.noPermission.dataViewExplanation": "データビューは、探索するElasticsearchデータを特定します。データビューを作成するには、必要な権限を管理者に依頼してください。", - "sharedUXPackages.noDataViewsPrompt.noPermission.title": "データビューを作成するための権限が必要です。", - "sharedUXPackages.noDataViewsPrompt.nowCreate": "ここでデータビューを作成します。", "sharedUXPackages.noDataViewsPrompt.readDocumentation": "ドキュメントを読む", "sharedUXPackages.noDataViewsPrompt.youHaveData": "Elasticsearchにデータがあります。", "sharedUXPackages.prompt.errors.notFound.body": "申し訳ございません。お探しのページは見つかりませんでした。削除または名前変更されたか、そもそも存在していなかった可能性があります。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index e1445a676c414..6b1d93bf2f686 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -7043,9 +7043,6 @@ "sharedUXPackages.fileUpload.uploadCompleteButtonLabel": "上传完成", "sharedUXPackages.fileUpload.uploadDoneToolTipContent": "您的文件已成功上传!", "sharedUXPackages.fileUpload.uploadingButtonLabel": "正在上传", - "sharedUXPackages.no_data_views.esqlButtonLabel": "语言:ES|QL", - "sharedUXPackages.no_data_views.esqlDocsLink": "了解详情。", - "sharedUXPackages.no_data_views.esqlMessage": "或者,您可以直接使用 ES|QL 查询数据。{docsLink}", "sharedUXPackages.noDataConfig.addIntegrationsDescription": "使用 Elastic 代理收集数据并增建分析解决方案。", "sharedUXPackages.noDataConfig.addIntegrationsTitle": "添加集成", "sharedUXPackages.noDataConfig.analytics": "分析", @@ -7067,8 +7064,6 @@ "sharedUXPackages.noDataViewsPrompt.dataViewExplanation": "数据视图标识您要浏览的 Elasticsearch 数据。您可以将数据视图指向一个或多个数据流、索引和索引别名(例如昨天的日志数据),或包含日志数据的所有索引。", "sharedUXPackages.noDataViewsPrompt.learnMore": "希望了解详情?", "sharedUXPackages.noDataViewsPrompt.noPermission.dataViewExplanation": "数据视图标识您要浏览的 Elasticsearch 数据。要创建数据视图,请联系管理员获得所需权限。", - "sharedUXPackages.noDataViewsPrompt.noPermission.title": "您需要权限以创建数据视图", - "sharedUXPackages.noDataViewsPrompt.nowCreate": "现在,创建数据视图。", "sharedUXPackages.noDataViewsPrompt.readDocumentation": "阅读文档", "sharedUXPackages.noDataViewsPrompt.youHaveData": "您在 Elasticsearch 中有数据。", "sharedUXPackages.prompt.errors.notFound.body": "抱歉,找不到您要查找的页面。该页面可能已移除、重命名,或可能根本不存在。", diff --git a/x-pack/test/functional/apps/data_views/feature_controls/security.ts b/x-pack/test/functional/apps/data_views/feature_controls/security.ts index 1cc62baf0abba..34317932a6b21 100644 --- a/x-pack/test/functional/apps/data_views/feature_controls/security.ts +++ b/x-pack/test/functional/apps/data_views/feature_controls/security.ts @@ -131,10 +131,12 @@ export default function ({ getPageObjects, getService }: FtrProviderContext) { expect(navLinks).to.eql(['Stack Management']); }); - it(`index pattern listing doesn't show create button`, async () => { + it(`index pattern listing shows disabled create button`, async () => { await settings.clickKibanaIndexPatterns(); await testSubjects.existOrFail('noDataViewsPrompt'); - await testSubjects.missingOrFail('createDataViewButton'); + const createDataViewButton = await testSubjects.find('createDataViewButton'); + const isDisabled = await createDataViewButton.getAttribute('disabled'); + expect(isDisabled).to.be('true'); }); it(`shows read-only badge`, async () => {