diff --git a/x-pack/packages/search/shared_ui/index.ts b/x-pack/packages/search/shared_ui/index.ts index 786fc67f4ea6..66b35fc50337 100644 --- a/x-pack/packages/search/shared_ui/index.ts +++ b/x-pack/packages/search/shared_ui/index.ts @@ -5,4 +5,7 @@ * 2.0. */ +export * from './src/connector_icon'; +export * from './src/decorative_horizontal_stepper'; export * from './src/form_info_field/form_info_field'; +export * from './src/search_empty_prompt'; diff --git a/x-pack/packages/search/shared_ui/src/connector_icon/connector_icon.tsx b/x-pack/packages/search/shared_ui/src/connector_icon/connector_icon.tsx new file mode 100644 index 000000000000..a37a3d8d9978 --- /dev/null +++ b/x-pack/packages/search/shared_ui/src/connector_icon/connector_icon.tsx @@ -0,0 +1,27 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiToolTip, EuiIcon } from '@elastic/eui'; + +interface ConnectorIconProps { + name: string; + serviceType: string; + iconPath?: string; + showTooltip?: boolean; +} + +export const ConnectorIcon: React.FC = ({ + name, + serviceType, + iconPath, + showTooltip = true, +}) => { + const icon = ; + + return showTooltip ? {icon} : icon; +}; diff --git a/x-pack/packages/search/shared_ui/src/connector_icon/index.ts b/x-pack/packages/search/shared_ui/src/connector_icon/index.ts new file mode 100644 index 000000000000..6bb7ae4a7a7b --- /dev/null +++ b/x-pack/packages/search/shared_ui/src/connector_icon/index.ts @@ -0,0 +1,8 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './connector_icon'; diff --git a/x-pack/packages/search/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx b/x-pack/packages/search/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx new file mode 100644 index 000000000000..414fe8d9a73f --- /dev/null +++ b/x-pack/packages/search/shared_ui/src/decorative_horizontal_stepper/decorative_horizontal_stepper.tsx @@ -0,0 +1,46 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiStepsHorizontal, EuiStepsHorizontalProps } from '@elastic/eui'; +import { css } from '@emotion/react'; + +interface DecorativeHorizontalStepperProps { + stepCount?: number; +} + +export const DecorativeHorizontalStepper: React.FC = ({ + stepCount = 2, +}) => { + // Generate the steps dynamically based on the stepCount prop + const horizontalSteps: EuiStepsHorizontalProps['steps'] = Array.from( + { length: stepCount }, + (_, index) => ({ + title: '', + status: 'incomplete', + onClick: () => {}, + }) + ); + + return ( + /* This is a presentational component, not intended for user interaction: + pointer-events: none, prevents user interaction with the component. + inert prevents click, focus, and other interactive events, removing it from the tab order. + role="presentation" indicates that this component is purely decorative and not interactive for assistive technologies. + Together, these attributes help ensure the component is accesible. */ + + ); +}; diff --git a/x-pack/packages/search/shared_ui/src/decorative_horizontal_stepper/index.ts b/x-pack/packages/search/shared_ui/src/decorative_horizontal_stepper/index.ts new file mode 100644 index 000000000000..d29c38492980 --- /dev/null +++ b/x-pack/packages/search/shared_ui/src/decorative_horizontal_stepper/index.ts @@ -0,0 +1,7 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +export * from './decorative_horizontal_stepper'; diff --git a/x-pack/packages/search/shared_ui/src/search_empty_prompt/index.ts b/x-pack/packages/search/shared_ui/src/search_empty_prompt/index.ts new file mode 100644 index 000000000000..0d4e70203ec3 --- /dev/null +++ b/x-pack/packages/search/shared_ui/src/search_empty_prompt/index.ts @@ -0,0 +1,8 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +export * from './search_empty_prompt'; diff --git a/x-pack/packages/search/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx b/x-pack/packages/search/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx new file mode 100644 index 000000000000..9099d75c2467 --- /dev/null +++ b/x-pack/packages/search/shared_ui/src/search_empty_prompt/search_empty_prompt.tsx @@ -0,0 +1,90 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiIcon, + EuiTitle, + EuiText, + EuiButtonEmpty, + EuiBadge, +} from '@elastic/eui'; + +interface BackButtonProps { + label: string; + onClickBack: () => void; +} +interface SearchEmptyPromptProps { + actions?: React.ReactNode; + backButton?: BackButtonProps; + body?: React.ReactNode; + description?: string; + icon?: string | React.JSXElementConstructor; + isComingSoon?: boolean; + comingSoonLabel?: string; + title: string; +} + +export const SearchEmptyPrompt: React.FC = ({ + actions, + backButton, + body, + description, + icon, + isComingSoon, + comingSoonLabel, + title, +}) => { + return ( + + + {backButton && ( + + + {backButton.label} + + + )} + {icon && ( + + + + )} + + +

{title}

+
+
+ {isComingSoon && ( + + {comingSoonLabel} + + )} + {description && ( + + +

{description}

+
+
+ )} + {body && <>{body}} + {actions && ( + + {actions} + + )} +
+
+ ); +}; diff --git a/x-pack/platform/plugins/private/translations/translations/fr-FR.json b/x-pack/platform/plugins/private/translations/translations/fr-FR.json index 3c7628ebbdd6..731044f9f61c 100644 --- a/x-pack/platform/plugins/private/translations/translations/fr-FR.json +++ b/x-pack/platform/plugins/private/translations/translations/fr-FR.json @@ -42632,13 +42632,11 @@ "xpack.serverlessSearch.connectors.typeLabel": "Type", "xpack.serverlessSearch.connectors.variablesTitle": "Variable pour votre {url}", "xpack.serverlessSearch.connectors.waitingForConnection": "En attente de connexion", - "xpack.serverlessSearch.connectorsEmpty.description": "La configuration et le déploiement d'un connecteur se passe entre la source de données tierce, votre terminal et l'UI sans serveur d'Elasticsearch. Le processus à haut niveau ressemble à ça :", "xpack.serverlessSearch.connectorsEmpty.dockerLabel": "Docker", "xpack.serverlessSearch.connectorsEmpty.guideOneDescription": "Choisissez une source de données à synchroniser", "xpack.serverlessSearch.connectorsEmpty.guideThreeDescription": "Saisissez les informations d'accès et de connexion pour votre source de données et exécutez votre première synchronisation", "xpack.serverlessSearch.connectorsEmpty.guideTwoDescription": "Déployez le code du connecteur sur votre propre infrastructure en exécutant {source} ou à l'aide de {docker}", "xpack.serverlessSearch.connectorsEmpty.sourceLabel": "source", - "xpack.serverlessSearch.connectorsEmpty.title": "Créer un connecteur", "xpack.serverlessSearch.connectorsPythonLink": "elastic/connecteurs", "xpack.serverlessSearch.connectorsTable.summaryLabel": "Affichage des {items} de {count} {connectors}", "xpack.serverlessSearch.disabled": "Désactivé", diff --git a/x-pack/platform/plugins/private/translations/translations/ja-JP.json b/x-pack/platform/plugins/private/translations/translations/ja-JP.json index 75df79316567..e262a4bb35a4 100644 --- a/x-pack/platform/plugins/private/translations/translations/ja-JP.json +++ b/x-pack/platform/plugins/private/translations/translations/ja-JP.json @@ -42489,13 +42489,11 @@ "xpack.serverlessSearch.connectors.typeLabel": "型", "xpack.serverlessSearch.connectors.variablesTitle": "{url}の変数", "xpack.serverlessSearch.connectors.waitingForConnection": "接続を待機中", - "xpack.serverlessSearch.connectorsEmpty.description": "コネクターを設定およびデプロイするには、サードパーティのデータソース、端末、ElasticsearchサーバーレスUI の間で作業することになります。プロセスの概要は次のとおりです。", "xpack.serverlessSearch.connectorsEmpty.dockerLabel": "Docker", "xpack.serverlessSearch.connectorsEmpty.guideOneDescription": "同期したいデータソースを選択します。", "xpack.serverlessSearch.connectorsEmpty.guideThreeDescription": "データソースのアクセスと接続の詳細情報を入力し、最初の同期を実行します", "xpack.serverlessSearch.connectorsEmpty.guideTwoDescription": "{source}から実行するか、{docker}を使用して、独自のインフラにコネクターコードをデプロイします。", "xpack.serverlessSearch.connectorsEmpty.sourceLabel": "ソース", - "xpack.serverlessSearch.connectorsEmpty.title": "コネクターを作成する", "xpack.serverlessSearch.connectorsPythonLink": "elastic/コネクター", "xpack.serverlessSearch.connectorsTable.summaryLabel": "{count} {connectors}中{items}を表示中", "xpack.serverlessSearch.disabled": "無効", diff --git a/x-pack/platform/plugins/private/translations/translations/zh-CN.json b/x-pack/platform/plugins/private/translations/translations/zh-CN.json index 59207bbfc580..f63f6602f725 100644 --- a/x-pack/platform/plugins/private/translations/translations/zh-CN.json +++ b/x-pack/platform/plugins/private/translations/translations/zh-CN.json @@ -41877,13 +41877,11 @@ "xpack.serverlessSearch.connectors.typeLabel": "类型", "xpack.serverlessSearch.connectors.variablesTitle": "您的 {url} 的变量", "xpack.serverlessSearch.connectors.waitingForConnection": "等待连接", - "xpack.serverlessSearch.connectorsEmpty.description": "要设置并部署连接器,您需要在第三方数据源、终端与 Elasticsearch 无服务器 UI 之间开展工作。高级流程类似于这样:", "xpack.serverlessSearch.connectorsEmpty.dockerLabel": "Docker", "xpack.serverlessSearch.connectorsEmpty.guideOneDescription": "选择要同步的数据源", "xpack.serverlessSearch.connectorsEmpty.guideThreeDescription": "输入您数据源的访问权限和连接详情,然后运行第一次同步", "xpack.serverlessSearch.connectorsEmpty.guideTwoDescription": "通过从 {source} 运行或使用 {docker} 在您自己的基础设施上部署连接器代码", "xpack.serverlessSearch.connectorsEmpty.sourceLabel": "源", - "xpack.serverlessSearch.connectorsEmpty.title": "创建连接器", "xpack.serverlessSearch.connectorsPythonLink": "Elastic/连接器", "xpack.serverlessSearch.connectorsTable.summaryLabel": "正在显示 {items} 个(共 {count} 个){connectors}", "xpack.serverlessSearch.disabled": "已禁用", diff --git a/x-pack/plugins/serverless_search/common/i18n_string.ts b/x-pack/plugins/serverless_search/common/i18n_string.ts index a6597ca915b6..43ae938b2b4d 100644 --- a/x-pack/plugins/serverless_search/common/i18n_string.ts +++ b/x-pack/plugins/serverless_search/common/i18n_string.ts @@ -59,6 +59,10 @@ export const TECH_PREVIEW_LABEL: string = i18n.translate('xpack.serverlessSearch defaultMessage: 'Tech preview', }); +export const COMING_SOON_LABEL: string = i18n.translate('xpack.serverlessSearch.comingSoon', { + defaultMessage: 'Coming soon', +}); + export const INVALID_JSON_ERROR: string = i18n.translate( 'xpack.serverlessSearch.invalidJsonError', { diff --git a/x-pack/plugins/serverless_search/public/application/components/connectors/elastic_managed_connector_coming_soon.tsx b/x-pack/plugins/serverless_search/public/application/components/connectors/elastic_managed_connector_coming_soon.tsx deleted file mode 100644 index 3057c6806fd7..000000000000 --- a/x-pack/plugins/serverless_search/public/application/components/connectors/elastic_managed_connector_coming_soon.tsx +++ /dev/null @@ -1,196 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiIcon, - EuiTitle, - EuiText, - EuiBadge, - EuiButtonEmpty, -} from '@elastic/eui'; - -import { i18n } from '@kbn/i18n'; - -// import { generatePath } from 'react-router-dom'; -import { SERVERLESS_ES_CONNECTORS_ID } from '@kbn/deeplinks-search/constants'; -import { useKibanaServices } from '../../hooks/use_kibana'; -import { useConnectorTypes } from '../../hooks/api/use_connector_types'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; - -import { BACK_LABEL } from '../../../../common/i18n_string'; -// import { BASE_CONNECTORS_PATH } from '../../constants'; -import { ConnectorIcon } from './connector_icon'; -import { DecorativeHorizontalStepper } from '../common/decorative_horizontal_stepper'; - -export const ElasticManagedConnectorComingSoon: React.FC = () => { - const connectorTypes = useConnectorTypes(); - - const connectorExamples = connectorTypes.filter((connector) => - ['Gmail', 'Sharepoint Online', 'Jira Cloud', 'Dropbox'].includes(connector.name) - ); - - const { - application: { navigateToApp }, - } = useKibanaServices(); - - const assetBasePath = useAssetBasePath(); - const connectorsIcon = assetBasePath + '/connectors.svg'; - return ( - - - - - - navigateToApp(SERVERLESS_ES_CONNECTORS_ID)} - > - {BACK_LABEL} - - - - - - - -

- {i18n.translate('xpack.serverlessSearch.elasticManagedConnectorEmpty.title', { - defaultMessage: 'Elastic managed connectors', - })} -

-
-
- - Coming soon - - - -

- {i18n.translate( - 'xpack.serverlessSearch.elasticManagedConnectorEmpty.description', - { - defaultMessage: - "We're actively developing Elastic managed connectors, that won't require any self-managed infrastructure. You'll be able to handle all configuration in the UI. This will simplify syncing your data into a serverless Elasticsearch project. This new workflow will have two steps:", - } - )} -

-
-
- - - - - - - - - - - - {connectorExamples.map((connector, index) => ( - - {index === Math.floor(connectorExamples.length / 2) && ( - - - - )} - - - - - ))} - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.elasticManagedConnectorEmpty.guideOneDescription', - { - defaultMessage: - "Choose from over 30 third-party data sources you'd like to sync", - } - )} -

-
-
-
-
- - - - - - - - - - - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.elasticManagedConnectorEmpty.guideThreeDescription', - { - defaultMessage: - 'Enter access and connection details for your data source and run your first sync using the Kibana UI', - } - )} -

-
-
-
-
-
-
-
-
-
-
-
-
- ); -}; diff --git a/x-pack/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx new file mode 100644 index 000000000000..a1e82319eab8 --- /dev/null +++ b/x-pack/plugins/serverless_search/public/application/components/connectors/elastic_managed_connectors_empty_prompt.tsx @@ -0,0 +1,144 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiPanel, EuiIcon, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { ConnectorIcon } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { SERVERLESS_ES_CONNECTORS_ID } from '@kbn/deeplinks-search/constants'; +import { BACK_LABEL } from '../../../../common/i18n_string'; +import { useKibanaServices } from '../../hooks/use_kibana'; +import { useConnectorTypes } from '../../hooks/api/use_connector_types'; +import { useAssetBasePath } from '../../hooks/use_asset_base_path'; + +export const ElasticManagedConnectorsEmptyPrompt: React.FC = () => { + const connectorTypes = useConnectorTypes(); + const connectorExamples = connectorTypes.filter((connector) => + ['Gmail', 'Sharepoint Online', 'Jira Cloud', 'Dropbox'].includes(connector.name) + ); + + const assetBasePath = useAssetBasePath(); + const connectorsIcon = assetBasePath + '/connectors.svg'; + const { + application: { navigateToApp }, + } = useKibanaServices(); + + return ( + navigateToApp(SERVERLESS_ES_CONNECTORS_ID), + }} + icon={connectorsIcon} + title={i18n.translate('xpack.serverlessSearch.elasticManagedConnectorEmpty.title', { + defaultMessage: 'Elastic managed connectors', + })} + description={i18n.translate( + 'xpack.serverlessSearch.elasticManagedConnectorEmpty.description', + { + defaultMessage: + "We're actively developing Elastic managed connectors, that won't require any self-managed infrastructure. You'll be able to handle all configuration in the UI. This will simplify syncing your data into a serverless Elasticsearch project. This new workflow will have two steps:", + } + )} + isComingSoon + body={ + + + + + + + + + + + + {connectorExamples.map((connector, index) => ( + + {index === Math.floor(connectorExamples.length / 2) && ( + + + + )} + + + + + ))} + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.elasticManagedConnectorEmpty.guideOneDescription', + { + defaultMessage: + "Choose from over 30 third-party data sources you'd like to sync", + } + )} +

+
+
+
+
+ + + + + + + + + + + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.elasticManagedConnectorEmpty.guideThreeDescription', + { + defaultMessage: + 'Enter access and connection details for your data source and run your first sync using the Kibana UI', + } + )} +

+
+
+
+
+
+
+
+
+ } + /> + ); +}; diff --git a/x-pack/plugins/serverless_search/public/application/components/connectors/empty_connectors_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/connectors/empty_connectors_prompt.tsx deleted file mode 100644 index 0767f8cfaf27..000000000000 --- a/x-pack/plugins/serverless_search/public/application/components/connectors/empty_connectors_prompt.tsx +++ /dev/null @@ -1,293 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiIcon, - EuiTitle, - EuiText, - EuiLink, - EuiButton, - EuiBadge, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import React from 'react'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import { docLinks } from '../../../../common/doc_links'; -import { useKibanaServices } from '../../hooks/use_kibana'; -import { useConnectorTypes } from '../../hooks/api/use_connector_types'; -import { useCreateConnector } from '../../hooks/api/use_create_connector'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; -import { useConnectors } from '../../hooks/api/use_connectors'; -import { DecorativeHorizontalStepper } from '../common/decorative_horizontal_stepper'; -import { ConnectorIcon } from './connector_icon'; - -import { ELASTIC_MANAGED_CONNECTOR_PATH, BASE_CONNECTORS_PATH } from '../../constants'; - -export const EmptyConnectorsPrompt: React.FC = () => { - const connectorTypes = useConnectorTypes(); - - const connectorExamples = connectorTypes.filter((connector) => - ['Gmail', 'Sharepoint Online', 'Jira Cloud', 'Dropbox'].includes(connector.name) - ); - const { createConnector, isLoading } = useCreateConnector(); - const { data } = useConnectors(); - - const assetBasePath = useAssetBasePath(); - const connectorsPath = assetBasePath + '/connectors.svg'; - - const { - application: { navigateToUrl }, - } = useKibanaServices(); - - return ( - - - - - - - - - -

- {i18n.translate('xpack.serverlessSearch.connectorsEmpty.title', { - defaultMessage: 'Set up a new connector', - })} -

-
-
- - -

- {i18n.translate('xpack.serverlessSearch.connectorsEmpty.description', { - defaultMessage: - "To set up and deploy a connector you'll be working between the third-party data source, your terminal, and the Elasticsearch serverless UI. The high level process looks like this:", - })} -

-
-
- - - - - - - - - - - - {connectorExamples.map((connector, index) => ( - - {index === Math.floor(connectorExamples.length / 2) && ( - - - - )} - - - - - ))} - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.connectorsEmpty.guideOneDescription', - { - defaultMessage: - "Choose from over 30 third-party data sources you'd like to sync", - } - )} -

-
-
-
-
- - - - - - - - - - - - - - - -

- - {i18n.translate( - 'xpack.serverlessSearch.connectorsEmpty.sourceLabel', - { defaultMessage: 'source' } - )} - - ), - docker: ( - - {i18n.translate( - 'xpack.serverlessSearch.connectorsEmpty.dockerLabel', - { defaultMessage: 'Docker' } - )} - - ), - }} - /> -

-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.connectorsEmpty.guideThreeDescription', - { - defaultMessage: - 'Enter access and connection details for your data source and run your first sync', - } - )} -

-
-
-
-
-
-
-
-
- - - createConnector()} - isLoading={isLoading} - > - {i18n.translate('xpack.serverlessSearch.connectorsEmpty.selfManagedButton', { - defaultMessage: 'Self-managed connector', - })} - - - - - - - navigateToUrl(`${BASE_CONNECTORS_PATH}/${ELASTIC_MANAGED_CONNECTOR_PATH}`) - } - > - {i18n.translate( - 'xpack.serverlessSearch.connectorsEmpty.elasticManagedButton', - { - defaultMessage: 'Elastic managed connector', - } - )} - - - - Coming soon - - - - -
-
-
-
- ); -}; diff --git a/x-pack/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx new file mode 100644 index 000000000000..d8805ceb6340 --- /dev/null +++ b/x-pack/plugins/serverless_search/public/application/components/connectors/self_managed_connectors_empty_prompt.tsx @@ -0,0 +1,256 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiIcon, + EuiLink, + EuiButton, + EuiBadge, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import React from 'react'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { ConnectorIcon } from '@kbn/search-shared-ui'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { docLinks } from '../../../../common/doc_links'; +import { useKibanaServices } from '../../hooks/use_kibana'; +import { useConnectorTypes } from '../../hooks/api/use_connector_types'; +import { useCreateConnector } from '../../hooks/api/use_create_connector'; +import { useAssetBasePath } from '../../hooks/use_asset_base_path'; +import { useConnectors } from '../../hooks/api/use_connectors'; +import { ELASTIC_MANAGED_CONNECTOR_PATH, BASE_CONNECTORS_PATH } from '../../constants'; +import { BACK_LABEL } from '../../../../common/i18n_string'; + +export const SelfManagedConnectorsEmptyPrompt: React.FC = () => { + const connectorTypes = useConnectorTypes(); + const connectorExamples = connectorTypes.filter((connector) => + ['Gmail', 'Sharepoint Online', 'Jira Cloud', 'Dropbox'].includes(connector.name) + ); + const { createConnector, isLoading } = useCreateConnector(); + const { data } = useConnectors(); + const assetBasePath = useAssetBasePath(); + const connectorsIcon = assetBasePath + '/connectors.svg'; + const { + application: { navigateToUrl }, + } = useKibanaServices(); + + return ( + + + + + + + + + + + + {connectorExamples.map((connector, index) => ( + + {index === Math.floor(connectorExamples.length / 2) && ( + + + + )} + + + + + ))} + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.connectorsEmpty.guideOneDescription', + { + defaultMessage: + "Choose from over 30 third-party data sources you'd like to sync", + } + )} +

+
+
+
+
+ + + + + + + + + + + + + + + +

+ + {i18n.translate( + 'xpack.serverlessSearch.connectorsEmpty.sourceLabel', + { defaultMessage: 'source' } + )} + + ), + docker: ( + + {i18n.translate( + 'xpack.serverlessSearch.connectorsEmpty.dockerLabel', + { defaultMessage: 'Docker' } + )} + + ), + }} + /> +

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.connectorsEmpty.guideThreeDescription', + { + defaultMessage: + 'Enter access and connection details for your data source and run your first sync', + } + )} +

+
+
+
+
+
+
+
+ + } + actions={ + + + createConnector()} + isLoading={isLoading} + > + {i18n.translate('xpack.serverlessSearch.connectorsEmpty.selfManagedButton', { + defaultMessage: 'Self-managed connector', + })} + + + + + + + navigateToUrl(`${BASE_CONNECTORS_PATH}/${ELASTIC_MANAGED_CONNECTOR_PATH}`) + } + > + {i18n.translate('xpack.serverlessSearch.connectorsEmpty.elasticManagedButton', { + defaultMessage: 'Elastic managed connector', + })} + + + + {BACK_LABEL} + + + + + } + /> + ); +}; diff --git a/x-pack/plugins/serverless_search/public/application/components/connectors_elastic_managed.tsx b/x-pack/plugins/serverless_search/public/application/components/connectors_elastic_managed.tsx index e645ede3d67e..63ab217b0c0f 100644 --- a/x-pack/plugins/serverless_search/public/application/components/connectors_elastic_managed.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/connectors_elastic_managed.tsx @@ -5,16 +5,13 @@ * 2.0. */ +import React, { useMemo } from 'react'; import { EuiLink, EuiPageTemplate, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import React, { useMemo } from 'react'; - import { LEARN_MORE_LABEL } from '../../../common/i18n_string'; - +import { ElasticManagedConnectorsEmptyPrompt } from './connectors/elastic_managed_connectors_empty_prompt'; import { useKibanaServices } from '../hooks/use_kibana'; -import { ElasticManagedConnectorComingSoon } from './connectors/elastic_managed_connector_coming_soon'; - import { docLinks } from '../../../common/doc_links'; export const ConnectorsElasticManaged = () => { @@ -55,7 +52,7 @@ export const ConnectorsElasticManaged = () => { - + {embeddableConsole} diff --git a/x-pack/plugins/serverless_search/public/application/components/connectors_overview.tsx b/x-pack/plugins/serverless_search/public/application/components/connectors_overview.tsx index 775cec8db155..42430df155e3 100644 --- a/x-pack/plugins/serverless_search/public/application/components/connectors_overview.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/connectors_overview.tsx @@ -20,16 +20,15 @@ import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo, useState } from 'react'; import { GithubLink } from '@kbn/search-api-panels'; +import { SelfManagedConnectorsEmptyPrompt } from './connectors/self_managed_connectors_empty_prompt'; import { docLinks } from '../../../common/doc_links'; import { LEARN_MORE_LABEL } from '../../../common/i18n_string'; import { useConnectors } from '../hooks/api/use_connectors'; import { useCreateConnector } from '../hooks/api/use_create_connector'; import { useKibanaServices } from '../hooks/use_kibana'; -import { EmptyConnectorsPrompt } from './connectors/empty_connectors_prompt'; import { ConnectorsTable } from './connectors/connectors_table'; import { ConnectorPrivilegesCallout } from './connectors/connector_config/connector_privileges_callout'; import { useAssetBasePath } from '../hooks/use_asset_base_path'; - import { BASE_CONNECTORS_PATH, ELASTIC_MANAGED_CONNECTOR_PATH } from '../constants'; const CALLOUT_KEY = 'search.connectors.ElasticManaged.ComingSoon.feedbackCallout'; @@ -42,15 +41,11 @@ export const ConnectorsOverview = () => { () => (consolePlugin?.EmbeddableConsole ? : null), [consolePlugin] ); - const canManageConnectors = !data || data.canManageConnectors; - const { application: { navigateToUrl }, } = useKibanaServices(); - const [showCallOut, setShowCallOut] = useState(sessionStorage.getItem(CALLOUT_KEY) !== 'hidden'); - const onDismiss = () => { setShowCallOut(false); sessionStorage.setItem(CALLOUT_KEY, 'hidden'); @@ -155,7 +150,7 @@ export const ConnectorsOverview = () => { ) : ( - + )} {embeddableConsole} diff --git a/x-pack/plugins/serverless_search/public/application/components/index_management/connector_empty_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/index_management/connector_empty_prompt.tsx index 487c80ce48b6..91d8ad707d42 100644 --- a/x-pack/plugins/serverless_search/public/application/components/index_management/connector_empty_prompt.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/index_management/connector_empty_prompt.tsx @@ -9,7 +9,7 @@ import React from 'react'; import { EuiButtonEmpty, EuiPanel } from '@elastic/eui'; import { BACK_LABEL } from '../../../../common/i18n_string'; -import { EmptyConnectorsPrompt } from '../connectors/empty_connectors_prompt'; +import { SelfManagedConnectorsEmptyPrompt } from '../connectors/self_managed_connectors_empty_prompt'; interface ConnectorIndexEmptyPromptProps { indexName: string; @@ -27,7 +27,7 @@ export const ConnectorIndexEmptyPrompt = ({ onBackClick }: ConnectorIndexEmptyPr > {BACK_LABEL} - + ); }; diff --git a/x-pack/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawler_coming_soon.tsx b/x-pack/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawler_coming_soon.tsx deleted file mode 100644 index ba146ed84799..000000000000 --- a/x-pack/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawler_coming_soon.tsx +++ /dev/null @@ -1,171 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiIcon, - EuiTitle, - EuiText, - EuiBadge, - EuiButtonEmpty, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; - -import { useKibanaServices } from '../../hooks/use_kibana'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; - -import { BACK_LABEL } from '../../../../common/i18n_string'; -import { DecorativeHorizontalStepper } from '../common/decorative_horizontal_stepper'; - -export const ElasticManagedWebCrawlersCommingSoon: React.FC = () => { - const { - application: { navigateToUrl }, - } = useKibanaServices(); - - const assetBasePath = useAssetBasePath(); - const webCrawlerIcon = assetBasePath + '/web_crawlers.svg'; - - return ( - - - - - - navigateToUrl(`./`)} - > - {BACK_LABEL} - - - - - - - -

- {i18n.translate('xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.title', { - defaultMessage: 'Elastic managed web crawlers', - })} -

-
-
- - Coming soon - - - -

- {i18n.translate( - 'xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.description', - { - defaultMessage: - "We're actively developing Elastic managed web crawlers, that won't require any self-managed infrastructure. You'll be able to handle all configuration in the UI. This will simplify syncing your data into a serverless Elasticsearch project. This new workflow will have two steps:", - } - )} -

-
-
- - - - - - - - - - - - - - - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.guideOneDescription', - { - defaultMessage: 'Set one or more domain URLs you want to crawl', - } - )} -

-
-
-
-
- - - - - - - - - - - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.guideThreeDescription', - { - defaultMessage: - 'Configure all the web crawler process using Kibana', - } - )} -

-
-
-
-
-
-
-
-
-
-
-
-
- ); -}; diff --git a/x-pack/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx new file mode 100644 index 000000000000..15160fc1b6a1 --- /dev/null +++ b/x-pack/plugins/serverless_search/public/application/components/web_crawlers/elastic_managed_web_crawlers_empty_prompt.tsx @@ -0,0 +1,121 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { EuiFlexGroup, EuiFlexItem, EuiIcon, EuiPanel, EuiText } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { SERVERLESS_ES_WEB_CRAWLERS_ID } from '@kbn/deeplinks-search/constants'; +import { BACK_LABEL, COMING_SOON_LABEL } from '../../../../common/i18n_string'; +import { useAssetBasePath } from '../../hooks/use_asset_base_path'; +import { useKibanaServices } from '../../hooks/use_kibana'; + +export const ElasticManagedWebCrawlersEmptyPrompt = () => { + const { + application: { navigateToApp }, + } = useKibanaServices(); + const assetBasePath = useAssetBasePath(); + const webCrawlersIcon = assetBasePath + '/web_crawlers.svg'; + + return ( + navigateToApp(SERVERLESS_ES_WEB_CRAWLERS_ID), + }} + icon={webCrawlersIcon} + title={i18n.translate('xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.title', { + defaultMessage: 'Elastic managed web crawlers', + })} + isComingSoon + comingSoonLabel={COMING_SOON_LABEL} + description={i18n.translate( + 'xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.description', + { + defaultMessage: + "We're actively developing Elastic managed web crawlers, that won't require any self-managed infrastructure. You'll be able to handle all configuration in the UI. This will simplify syncing your data into a serverless Elasticsearch project. This new workflow will have two steps:", + } + )} + body={ + + + + + + + + + + + + + + + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.guideOneDescription', + { + defaultMessage: 'Set one or more domain URLs you want to crawl', + } + )} +

+
+
+
+
+ + + + + + + + + + + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.elasticManagedWebCrawlerEmpty.guideThreeDescription', + { + defaultMessage: 'Configure all the web crawler process using Kibana', + } + )} +

+
+
+
+
+
+
+
+
+ } + /> + ); +}; diff --git a/x-pack/plugins/serverless_search/public/application/components/web_crawlers/empty_web_crawlers_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/web_crawlers/empty_web_crawlers_prompt.tsx deleted file mode 100644 index 20c05f86747a..000000000000 --- a/x-pack/plugins/serverless_search/public/application/components/web_crawlers/empty_web_crawlers_prompt.tsx +++ /dev/null @@ -1,270 +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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React from 'react'; -import { - EuiFlexGroup, - EuiFlexItem, - EuiPanel, - EuiIcon, - EuiTitle, - EuiText, - EuiLink, - EuiButton, - EuiBadge, -} from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; - -import { useKibanaServices } from '../../hooks/use_kibana'; -import { useAssetBasePath } from '../../hooks/use_asset_base_path'; - -import { ELASTIC_MANAGED_WEB_CRAWLERS_PATH, BASE_WEB_CRAWLERS_PATH } from '../../constants'; -import { DecorativeHorizontalStepper } from '../common/decorative_horizontal_stepper'; - -export const EmptyWebCrawlersPrompt: React.FC = () => { - const { - application: { navigateToUrl }, - } = useKibanaServices(); - - const assetBasePath = useAssetBasePath(); - const webCrawlersIcon = assetBasePath + '/web_crawlers.svg'; - const githubIcon = assetBasePath + '/github_white.svg'; - - return ( - - - - - - - - - -

- {i18n.translate('xpack.serverlessSearch.webCrawlersEmpty.title', { - defaultMessage: 'Set up a web crawler', - })} -

-
-
- - -

- {i18n.translate('xpack.serverlessSearch.webCrawlersEmpty.description', { - defaultMessage: - "To set up and deploy a web crawler you'll be working between data source, your terminal, and the Kibana UI. The high level process looks like this:", - })} -

-
-
- - - - - - - - - - - - - - - - - - - - - - -

- - {i18n.translate( - 'xpack.serverlessSearch.webCrawlersEmpty.sourceLabel', - { defaultMessage: 'source' } - )} - - ), - docker: ( - - {i18n.translate( - 'xpack.serverlessSearch.webCrawlersEmpty.dockerLabel', - { defaultMessage: 'Docker' } - )} - - ), - }} - /> -

-
-
-
-
- - - - - - - - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.webCrawlersEmpty.guideOneDescription', - { - defaultMessage: 'Set one or more domain URLs you want to crawl', - } - )} -

-
-
-
-
- - - - - - - - - - - - - - - - - - - - - - - - -

- {i18n.translate( - 'xpack.serverlessSearch.webCrawlersEmpty.guideThreeDescription', - { - defaultMessage: - 'Configure your web crawler and connect it to Elasticsearch', - } - )} -

-
-
-
-
-
-
-
-
- - - - {i18n.translate('xpack.serverlessSearch.webCrawlersEmpty.selfManagedButton', { - defaultMessage: 'Self-managed web crawler', - })} - - - - - - - navigateToUrl( - `${BASE_WEB_CRAWLERS_PATH}/${ELASTIC_MANAGED_WEB_CRAWLERS_PATH}` - ) - } - > - {i18n.translate( - 'xpack.serverlessSearch.webCrawlersEmpty.elasticManagedButton', - { - defaultMessage: 'Elastic managed web crawler', - } - )} - - - - Coming soon - - - - -
-
-
-
- ); -}; diff --git a/x-pack/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx b/x-pack/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx new file mode 100644 index 000000000000..b820e7704c85 --- /dev/null +++ b/x-pack/plugins/serverless_search/public/application/components/web_crawlers/self_managed_web_crawlers_empty_prompt.tsx @@ -0,0 +1,229 @@ +/* + * 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; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import React from 'react'; +import { + EuiBadge, + EuiButton, + EuiFlexGroup, + EuiFlexItem, + EuiIcon, + EuiLink, + EuiPanel, + EuiText, +} from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; +import { SearchEmptyPrompt, DecorativeHorizontalStepper } from '@kbn/search-shared-ui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import { ELASTIC_MANAGED_WEB_CRAWLERS_PATH, BASE_WEB_CRAWLERS_PATH } from '../../constants'; +import { COMING_SOON_LABEL } from '../../../../common/i18n_string'; +import { useKibanaServices } from '../../hooks/use_kibana'; +import { useAssetBasePath } from '../../hooks/use_asset_base_path'; + +export const SelfManagedWebCrawlersEmptyPrompt = () => { + const { + application: { navigateToUrl }, + } = useKibanaServices(); + + const assetBasePath = useAssetBasePath(); + const webCrawlersIcon = assetBasePath + '/web_crawlers.svg'; + const githubIcon = assetBasePath + '/github_white.svg'; + + return ( + + + + + + + + + + + + + + + + + + + + + + +

+ + {i18n.translate( + 'xpack.serverlessSearch.webCrawlersEmpty.sourceLabel', + { defaultMessage: 'source' } + )} + + ), + docker: ( + + {i18n.translate( + 'xpack.serverlessSearch.webCrawlersEmpty.dockerLabel', + { defaultMessage: 'Docker' } + )} + + ), + }} + /> +

+
+
+
+
+ + + + + + + + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.webCrawlersEmpty.guideOneDescription', + { + defaultMessage: 'Set one or more domain URLs you want to crawl', + } + )} +

+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +

+ {i18n.translate( + 'xpack.serverlessSearch.webCrawlersEmpty.guideThreeDescription', + { + defaultMessage: + 'Configure your web crawler and connect it to Elasticsearch', + } + )} +

+
+
+
+
+
+
+
+ + } + actions={ + <> + + + {i18n.translate('xpack.serverlessSearch.webCrawlersEmpty.selfManagedButton', { + defaultMessage: 'Self-managed web crawler', + })} + + + + + + + navigateToUrl(`${BASE_WEB_CRAWLERS_PATH}/${ELASTIC_MANAGED_WEB_CRAWLERS_PATH}`) + } + > + {i18n.translate('xpack.serverlessSearch.webCrawlersEmpty.elasticManagedButton', { + defaultMessage: 'Elastic managed web crawler', + })} + + + + {COMING_SOON_LABEL} + + + + + } + /> + ); +}; diff --git a/x-pack/plugins/serverless_search/public/application/components/web_crawlers_elastic_managed.tsx b/x-pack/plugins/serverless_search/public/application/components/web_crawlers_elastic_managed.tsx index 0cf3445f0a5b..e2594cc621f4 100644 --- a/x-pack/plugins/serverless_search/public/application/components/web_crawlers_elastic_managed.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/web_crawlers_elastic_managed.tsx @@ -9,11 +9,9 @@ import { EuiLink, EuiPageTemplate, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import React, { useMemo } from 'react'; - import { LEARN_MORE_LABEL } from '../../../common/i18n_string'; - import { useKibanaServices } from '../hooks/use_kibana'; -import { ElasticManagedWebCrawlersCommingSoon } from './web_crawlers/elastic_managed_web_crawler_coming_soon'; +import { ElasticManagedWebCrawlersEmptyPrompt } from './web_crawlers/elastic_managed_web_crawlers_empty_prompt'; export const WebCrawlersElasticManaged = () => { const { console: consolePlugin } = useKibanaServices(); @@ -54,7 +52,7 @@ export const WebCrawlersElasticManaged = () => { - + {embeddableConsole} diff --git a/x-pack/plugins/serverless_search/public/application/components/web_crawlers_overview.tsx b/x-pack/plugins/serverless_search/public/application/components/web_crawlers_overview.tsx index 1a112304df69..e9e31f6c074c 100644 --- a/x-pack/plugins/serverless_search/public/application/components/web_crawlers_overview.tsx +++ b/x-pack/plugins/serverless_search/public/application/components/web_crawlers_overview.tsx @@ -5,15 +5,13 @@ * 2.0. */ +import React, { useMemo } from 'react'; import { EuiLink, EuiPageTemplate, EuiText } from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; -import React, { useMemo } from 'react'; - import { LEARN_MORE_LABEL } from '../../../common/i18n_string'; - import { useKibanaServices } from '../hooks/use_kibana'; -import { EmptyWebCrawlersPrompt } from './web_crawlers/empty_web_crawlers_prompt'; +import { SelfManagedWebCrawlersEmptyPrompt } from './web_crawlers/self_managed_web_crawlers_empty_prompt'; export const WebCrawlersOverview = () => { const { console: consolePlugin } = useKibanaServices(); @@ -54,7 +52,7 @@ export const WebCrawlersOverview = () => { - + {embeddableConsole} diff --git a/x-pack/plugins/serverless_search/tsconfig.json b/x-pack/plugins/serverless_search/tsconfig.json index 854a90fdb5fb..1af7677bc498 100644 --- a/x-pack/plugins/serverless_search/tsconfig.json +++ b/x-pack/plugins/serverless_search/tsconfig.json @@ -56,5 +56,6 @@ "@kbn/security-plugin-types-public", "@kbn/deeplinks-search", "@kbn/core-application-browser", + "@kbn/search-shared-ui", ] }