[8.12] Language client getting started dedicated (#172869) (#172987)

# Backport

This will backport the following commits from `main` to `8.12`:
- [Language client getting started dedicated
(#172869)](https://github.com/elastic/kibana/pull/172869)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Sander
Philipse","email":"94373878+sphilipse@users.noreply.github.com"},"sourceCommit":{"committedDate":"2023-12-08T18:48:56Z","message":"Language
client getting started dedicated (#172869)\n\n## Summary\r\n\r\nThis
adds the getting started page from Serverless Elasticsearch
to\r\nDedicated.","sha":"8b9ce1848ca59291a759396e61389a76e0d17133","branchLabelMapping":{"^v8.13.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:EnterpriseSearch","v8.12.0","v8.13.0"],"number":172869,"url":"https://github.com/elastic/kibana/pull/172869","mergeCommit":{"message":"Language
client getting started dedicated (#172869)\n\n## Summary\r\n\r\nThis
adds the getting started page from Serverless Elasticsearch
to\r\nDedicated.","sha":"8b9ce1848ca59291a759396e61389a76e0d17133"}},"sourceBranch":"main","suggestedTargetBranches":["8.12"],"targetPullRequestStates":[{"branch":"8.12","label":"v8.12.0","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"},{"branch":"main","label":"v8.13.0","labelRegex":"^v8.13.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/172869","number":172869,"mergeCommit":{"message":"Language
client getting started dedicated (#172869)\n\n## Summary\r\n\r\nThis
adds the getting started page from Serverless Elasticsearch
to\r\nDedicated.","sha":"8b9ce1848ca59291a759396e61389a76e0d17133"}}]}]
BACKPORT-->

Co-authored-by: Sander Philipse <94373878+sphilipse@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2023-12-08 15:03:03 -05:00 committed by GitHub
parent 39954f572f
commit ed5fd5a735
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 1045 additions and 2346 deletions

View file

@ -0,0 +1,142 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/
import React, { useState } from 'react';
import {
EuiCheckableCard,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiSpacer,
EuiText,
EuiThemeProvider,
EuiTitle,
EuiBadge,
EuiPanelProps,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { OverviewPanel } from '..';
import { ELASTICSEARCH_URL_PLACEHOLDER } from '../constants';
export interface CloudDetailsPanelProps {
cloudId?: string;
elasticsearchUrl?: string;
isPanelLeft?: boolean;
overviewPanelProps?: Partial<EuiPanelProps>;
}
enum CloudDetail {
ElasticsearchEndpoint = 'es_url',
CloudId = 'cloud_id',
}
export const CloudDetailsPanel = ({
cloudId,
elasticsearchUrl = ELASTICSEARCH_URL_PLACEHOLDER,
isPanelLeft = true,
overviewPanelProps,
}: CloudDetailsPanelProps) => {
const [selectedDetail, setSelectedCloudDetail] = useState<CloudDetail>(
CloudDetail.ElasticsearchEndpoint
);
const panelContent = (
<EuiThemeProvider colorMode="dark">
<EuiPanel paddingSize="xs">
<EuiCodeBlock isCopyable fontSize="m" className="serverlessSearchCloudDetailsCopyPanel">
{selectedDetail === CloudDetail.CloudId && cloudId}
{selectedDetail === CloudDetail.ElasticsearchEndpoint && elasticsearchUrl}
</EuiCodeBlock>
</EuiPanel>
</EuiThemeProvider>
);
return (
<OverviewPanel
description={i18n.translate('searchApiPanels.cloudIdDetails.description', {
defaultMessage: 'Get ready to ingest and query your data by choosing a connection option:',
})}
leftPanelContent={isPanelLeft ? panelContent : undefined}
rightPanelContent={isPanelLeft ? undefined : panelContent}
links={[]}
title={i18n.translate('searchApiPanels.cloudIdDetails.title', {
defaultMessage: 'Copy your connection details',
})}
overviewPanelProps={overviewPanelProps}
>
<EuiSpacer size="l" />
<EuiCheckableCard
id={CloudDetail.ElasticsearchEndpoint}
name={CloudDetail.ElasticsearchEndpoint}
label={
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="searchApiPanels.cloudIdDetails.elasticsearchEndpoint.title"
defaultMessage="Elasticsearch endpoint"
/>
</h5>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<span>
<EuiBadge color="success">
<FormattedMessage
id="searchApiPanels.cloudIdDetails.elasticsearchEndpoint.recommendedBadge"
defaultMessage="Recommended"
/>
</EuiBadge>
</span>
</EuiFlexItem>
</EuiFlexGroup>
}
checked={selectedDetail === CloudDetail.ElasticsearchEndpoint}
onChange={() => setSelectedCloudDetail(CloudDetail.ElasticsearchEndpoint)}
>
<EuiText size="s">
<p>
<FormattedMessage
id="searchApiPanels.cloudIdDetails.elasticsearchEndpoint.description"
defaultMessage="The most common method for establishing an Elasticsearch connection."
/>
</p>
</EuiText>
</EuiCheckableCard>
<EuiSpacer />
{Boolean(cloudId) && (
<EuiCheckableCard
id={CloudDetail.CloudId}
name={CloudDetail.CloudId}
label={
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="searchApiPanels.cloudIdDetails.cloudId.title"
defaultMessage="Cloud ID"
/>
</h5>
</EuiTitle>
}
checked={selectedDetail === CloudDetail.CloudId}
onChange={() => setSelectedCloudDetail(CloudDetail.CloudId)}
>
<EuiText size="s">
<p>
<FormattedMessage
id="searchApiPanels.cloudIdDetails.cloudId.description"
defaultMessage="Specific client libraries and connectors can use this unique identifier specific to Elastic Cloud."
/>
</p>
</EuiText>
</EuiCheckableCard>
)}
</OverviewPanel>
);
};

View file

@ -1,8 +1,9 @@
/*
* 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.
* 2.0 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 or the Server
* Side Public License, v 1.
*/
import React from 'react';
@ -19,11 +20,17 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useAssetBasePath } from '../hooks/use_asset_base_path';
export const PipelinePanel: React.FC = () => {
const assetBasePath = useAssetBasePath();
interface PipelinePanelProps {
clusterImage: string;
cutImage: string;
reporterImage: string;
}
export const PipelinePanel: React.FC<PipelinePanelProps> = ({
clusterImage,
cutImage,
reporterImage,
}) => {
return (
<EuiThemeProvider colorMode="dark">
<EuiPanel paddingSize="xl">
@ -31,24 +38,21 @@ export const PipelinePanel: React.FC = () => {
<EuiFlexItem>
<EuiFlexGroup alignItems="flexStart" justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiImage alt="cluster" src={`${assetBasePath}/cluster.svg`} />
<EuiImage alt="" src={clusterImage} />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle size="s">
<h3>
{i18n.translate(
'xpack.serverlessSearch.pipeline.overview.dataEnrichment.title',
{
defaultMessage: 'Enrich Data',
}
)}
{i18n.translate('searchApiPanels.pipeline.overview.dataEnrichment.title', {
defaultMessage: 'Enrich Data',
})}
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s">
<p>
{i18n.translate(
'xpack.serverlessSearch.pipeline.overview.dataEnrichment.description',
'searchApiPanels.pipeline.overview.dataEnrichment.description',
{
defaultMessage:
'Add information from external sources or apply transformations to your documents for more contextual, insightful search.',
@ -62,28 +66,22 @@ export const PipelinePanel: React.FC = () => {
<EuiFlexItem>
<EuiFlexGroup alignItems="flexStart" justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiImage alt="cut" src={`${assetBasePath}/cut.svg`} />
<EuiImage alt="" src={cutImage} />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle size="s">
<h3>
{i18n.translate(
'xpack.serverlessSearch.pipeline.overview.extAndStandard.title',
{
defaultMessage: 'Extract and standardize',
}
)}
{i18n.translate('searchApiPanels.pipeline.overview.extAndStandard.title', {
defaultMessage: 'Extract and standardize',
})}
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s">
{i18n.translate(
'xpack.serverlessSearch.pipeline.overview.extAndStandard.description',
{
defaultMessage:
'Parse information from your documents to ensure they conform to a standardized format.',
}
)}
{i18n.translate('searchApiPanels.pipeline.overview.extAndStandard.description', {
defaultMessage:
'Parse information from your documents to ensure they conform to a standardized format.',
})}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
@ -91,28 +89,21 @@ export const PipelinePanel: React.FC = () => {
<EuiFlexItem>
<EuiFlexGroup alignItems="flexStart" justifyContent="flexStart">
<EuiFlexItem grow={false}>
<EuiImage alt="reporter" src={`${assetBasePath}/reporter.svg`} />
<EuiImage alt="" src={reporterImage} />
</EuiFlexItem>
<EuiFlexItem>
<EuiTitle size="s">
<h3>
{i18n.translate(
'xpack.serverlessSearch.pipeline.overview.anonymization.title',
{
defaultMessage: 'Anonymize data',
}
)}
{i18n.translate('searchApiPanels.pipeline.overview.anonymization.title', {
defaultMessage: 'Anonymize data',
})}
</h3>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText size="s">
{i18n.translate(
'xpack.serverlessSearch.pipeline.overview.anonymization.description',
{
defaultMessage:
'Remove sensitive information from documents before indexing.',
}
)}
{i18n.translate('searchApiPanels.pipeline.overview.anonymization.description', {
defaultMessage: 'Remove sensitive information from documents before indexing.',
})}
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>

View file

@ -11,12 +11,14 @@ import { EuiFlexGroup, EuiFlexItem, EuiTitle, EuiSpacer, EuiImage, EuiText } fro
import { i18n } from '@kbn/i18n';
import { AuthenticatedUser } from '@kbn/security-plugin/common';
export * from './components/cloud_details';
export * from './components/code_box';
export * from './components/github_link';
export * from './components/ingest_data';
export * from './components/ingestions_panel';
export * from './components/language_client_panel';
export * from './components/overview_panel';
export * from './components/pipeline_panel';
export * from './components/select_client';
export * from './components/try_in_console_button';
export * from './components/install_client';

View file

@ -1,57 +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 { setMockValues } from '../../../__mocks__/kea_logic';
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import * as Languages from './languages';
import { ElasticsearchClientInstructions } from '.';
describe('Elasticsearch Client Instructions', () => {
let wrapper: ShallowWrapper;
afterEach(() => {
jest.clearAllMocks();
});
const setup = (language: string) => {
setMockValues({
cloud: {
cloudId: 'example-cloud-id',
},
});
wrapper = shallow(<ElasticsearchClientInstructions language={language} />);
};
describe('Displaying the right language options', () => {
it.concurrent.each([
['dotnet', Languages.ElasticsearchDotnet, false],
['go', Languages.ElasticsearchGo, true],
['java', Languages.ElasticsearchJava, false],
['javascript', Languages.ElasticsearchJavascript, true],
['php', Languages.ElasticsearchPhp, true],
['python', Languages.ElasticsearchPython, true],
['ruby', Languages.ElasticsearchRuby, true],
['rust', Languages.ElasticsearchRust, false],
])('%s', (language, Component, hasCloudIdProp) => {
setup(language);
expect(wrapper.find(Component)).toHaveLength(1);
expect(wrapper.find(Component).prop('cloudId')).toEqual(
hasCloudIdProp ? 'example-cloud-id' : undefined
);
});
});
it('does not display language for unrecognised language', () => {
setup('coffeescript');
expect(wrapper.isEmptyRender()).toEqual(true);
});
});

View file

@ -1,53 +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 { useValues } from 'kea';
import { KibanaLogic } from '../../../shared/kibana';
import {
ElasticsearchDotnet,
ElasticsearchGo,
ElasticsearchJava,
ElasticsearchJavascript,
ElasticsearchPhp,
ElasticsearchPython,
ElasticsearchRuby,
ElasticsearchRust,
} from './languages';
const useCloudId = (): string | undefined => {
const { cloud } = useValues(KibanaLogic);
return cloud?.cloudId;
};
export const ElasticsearchClientInstructions: React.FC<{ language: string }> = ({ language }) => {
const cloudId = useCloudId();
switch (language) {
case 'dotnet':
return <ElasticsearchDotnet />;
case 'go':
return <ElasticsearchGo cloudId={cloudId} />;
case 'java':
return <ElasticsearchJava />;
case 'javascript':
return <ElasticsearchJavascript cloudId={cloudId} />;
case 'php':
return <ElasticsearchPhp cloudId={cloudId} />;
case 'python':
return <ElasticsearchPython cloudId={cloudId} />;
case 'ruby':
return <ElasticsearchRuby cloudId={cloudId} />;
case 'rust':
return <ElasticsearchRust />;
default:
return null;
}
};

View file

@ -1,8 +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.
*/
export { ElasticsearchClientInstructions } from './elasticsearch_client_instructions';

View file

@ -1,155 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchDotnet: React.FC<{ cloudId?: string }> = ({ cloudId }) => {
return (
<>
<EuiText>
<p>
The official .Net client for Elasticsearch includes all the features you need to add
search to a .Net application:
</p>
<ul>
<li>One-to-one mapping with REST API.</li>
<li>Strongly typed requests and responses for Elasticsearch APIs.</li>
<li>Fluent API for building requests.</li>
<li>Helpers for common tasks such as bulk indexing of documents.</li>
<li>Pluggable serialization of requests and responses based on System.Text.Json.</li>
<li>Diagnostics, auditing, and .NET activity integration.</li>
</ul>
<p>
The .NET Elasticsearch client is built upon the Elastic Transport library which provides:
</p>
<ul>
<li>Connection management and load balancing across all available nodes.</li>
<li>Request retries and dead connections handling.</li>
</ul>
<EuiLink target="_blank" href={docLinks.clientsNetIntroduction}>
Learn more about the official .NET clients for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-net">
The official Elasticsearch .NET clients on Github
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>
For SDK style projects, you can install the Elasticsearch client by running the following
.NET CLI command in your terminal:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
{dedent`
dotnet add package Elastic.Clients.Elasticsearch
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>
This command adds a package reference to your project (csproj) file for the latest stable
version of the client.
</p>
<p>
If you prefer, you may also manually add a package reference inside your project file:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
{dedent`
<PackageReference Include="Elastic.Clients.Elasticsearch" Version="ELASTICSAERCH VERSION" />
`}
</EuiCodeBlock>
<EuiSpacer />
<EuiText>
<p>
For Visual Studio users, the .NET client can also be installed from the Package Manager
Console inside Visual Studio using the following command:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
{dedent`
Install-Package Elastic.Clients.Elasticsearch
`}
</EuiCodeBlock>
<EuiSpacer />
<EuiText>
<p>
Alternatively, search for Elastic.Clients.Elasticsearch in the NuGet Package Manager UI.
</p>
</EuiText>
<EuiSpacer />
{cloudId ? (
<>
<EuiText>
<h4>Connecting to Elastic Cloud</h4>
<p>
Connecting to an Elasticsearch Service deployment is achieved by providing the unique
Cloud ID for your deployment when configuring the ElasticsearchClient instance. You
can retrieve the Cloud ID from the homepage of the deployment in Elasticsearch
Service. You also require suitable credentials that your application uses to
authenticate with your deployment.
</p>
<p>
As a security best practice, it is recommended to create a dedicated API key per
application, with permissions limited to only those required for any API calls the
application is authorized to make.
</p>
<p>
The following snippet shows you how to create a client instance that connects to an
Elasticsearch deployment in the cloud.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="python">
{dedent`
using Elastic.Clients.Elasticsearch;
using Elastic.Transport;
var client = new ElasticsearchClient("${cloudId}", new ApiKey("<API_KEY>"));
`}
</EuiCodeBlock>
</>
) : (
<>
<EuiText>
<h4>Connecting to Elasticsearch</h4>
<p>
The .Net client for Elasticsearch supports connecting to single nodes as well as
multiple nodes utilizing a node pool.{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsNetSingleNode}>
Visit the documentation to learn more about connecting to Elasticsearch.
</a>
</p>
</EuiText>
</>
)}
</>
);
};

View file

@ -1,139 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchGo: React.FC<{ cloudId?: string }> = ({ cloudId }) => {
return (
<>
<EuiText>
<p>
The official Go client for Elasticsearch includes all the features you need to add search
to a Go application:
</p>
<ul>
<li>One-to-one mapping with the Elasticsearch REST API</li>
<li>Generalized, pluggable architecture</li>
<li>Helpers for convenience</li>
<li>A rich set of examples in the documentation</li>
</ul>
<EuiLink target="_blank" href={docLinks.clientsGoIndex}>
Learn more about the Go client for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/go-elasticsearch">
The Go client for Elasticsearch on Github
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://godoc.org/github.com/elastic/go-elasticsearch">
View the documentation on GoDoc
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>Add the package to your go.mod file:</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="go-module">
{dedent`
require github.com/elastic/go-elasticsearch/v8 main
`}
</EuiCodeBlock>
<EuiSpacer />
<EuiText>
<h4>Getting started</h4>
<p>
The <code>elasticsearch</code> package ties together two separate packages for calling the
Elasticsearch APIs and transferring data over HTTP: <code>esapi</code> and{' '}
<code>elastictransport</code>.
</p>
<p>
Use the <code>elasticsearch.NewDefaultClient()</code> function to create the client with
the default settings.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="go">
{dedent`
es, err := elasticsearch.NewDefaultClient()
if err != nil {
log.Fatalf("Error creating the client: %s", err)
}
res, err := es.Info()
if err != nil {
log.Fatalf("Error getting response: %s", err)
}
defer res.Body.Close()
log.Println(res)
`}
</EuiCodeBlock>
<EuiSpacer />
{cloudId ? (
<>
<EuiText>
<h4>Connecting to Elastic Cloud</h4>
<p>
If you are using Elastic Cloud, the client offers an easy way to connect to it. You
must pass your Cloud ID to the client, which is found in the Cloud console, as well as
a corresponding API key.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="go">
{dedent`
cfg := elasticsearch.Config{
CloudID: "${cloudId}",
APIKey: "API_KEY"
}
es, err := elasticsearch.NewClient(cfg)
`}
</EuiCodeBlock>
</>
) : (
<>
<EuiText>
<h4>Connecting to Elasticsearch</h4>
<p>
To set the cluster endpoint(s) programmatically, pass a configuration object to the{' '}
<code>elasticsearch.NewClient()</code> function. To set the username and password,
include them in the endpoint URL, or use the corresponding configuration options.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="go">
{dedent`
cfg := elasticsearch.Config{
Addresses: []string{
"http://localhost:9200",
"http://localhost:9201",
},
Username: "<username>",
Password: "<password>",
}
es, err := elasticsearch.NewClient(cfg)
`}
</EuiCodeBlock>
</>
)}
</>
);
};

View file

@ -1,107 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchJava: React.FC = () => {
return (
<>
<EuiText>
<p>
The Elasticsearch Java API Client includes all the features you need to add search to a
Java application:
</p>
<ul>
<li>Strongly typed requests and responses for all Elasticsearch APIs.</li>
<li>Blocking and asynchronous versions of all APIs.</li>
<li>
Use of fluent builders and functional patterns to allow writing concise yet readable
code when creating complex nested structures.
</li>
<li>
Seamless integration of application classes by using an object mapper such as Jackson or
any JSON-B implementation.
</li>
</ul>
<EuiLink target="_blank" href={docLinks.clientsJavaIntroduction}>
Learn more about the Elasticsearch JAVA API client
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-java">
The Elasticsearch JAVA API client on Github
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>
There are several ways to install the Java API client.{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsJavaInstallation}>
Visit the client documentation to learn more
</a>
.
</p>
<h4>Connecting to Elasticsearch</h4>
<p>The client is structured around three main components:</p>
<ul>
<li>
<strong>API client classes.</strong> These provide strongly typed data structures and
methods for Elasticsearch APIs. Since the Elasticsearch API is large, it is structured
in feature groups (also called namespaces), each having its own client class.
Elasticsearch core features are implemented in the ElasticsearchClient class.
</li>
<li>
<strong>A JSON object mapper.</strong> This maps your application classes to JSON and
seamlessly integrates them with the API client.
</li>
<li>
<strong>A transport layer implementation.</strong> This is where all HTTP request
handling takes place.
</li>
</ul>
<p>The code snippet below creates and wires these three components together:</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="java">
{dedent`
// Create the low-level client
RestClient restClient = RestClient.builder(
new HttpHost("localhost", 9200)).build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(
restClient, new JacksonJsonpMapper());
// And create the API client
ElasticsearchClient client = new ElasticsearchClient(transport);
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>
Authentication is managed by the{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsJavaRestLow}>
Java Low Level REST Client
</a>
. For further details on configuring authentication, refer to{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsJavaBasicAuthentication}>
its documentation
</a>
.
</p>
</EuiText>
</>
);
};

View file

@ -1,97 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchJavascript: React.FC<{ cloudId?: string }> = ({ cloudId }) => {
return (
<>
<EuiText>
<p>
This is the official Node.js client for Elasticsearch includes all the features you need
to add search to any Node.js application:
</p>
<ul>
<li>One-to-one mapping with REST API.</li>
<li>Generalized, pluggable architecture.</li>
<li>Configurable, automatic discovery of cluster nodes.</li>
<li>Persistent, Keep-Alive connections.</li>
<li>Load balancing across all available nodes.</li>
<li>Child client support.</li>
<li>TypeScript support out of the box.</li>
</ul>
<EuiLink target="_blank" href={docLinks.clientsJsIntro}>
Learn more about the official Node.js client for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-js">
The official Node.js client for Elasticsearch on Github
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>To install the latest version of the client, run the following command:</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
npm install @elastic/elasticsearch
</EuiCodeBlock>
<EuiSpacer />
{cloudId ? (
<>
<EuiText>
<h4>Connecting to Elastic Cloud</h4>
<p>
If you are using Elastic Cloud, the client offers an easy way to connect to it via the
cloud option. You must pass the Cloud ID that you can find in the cloud console, then
your username and password inside the auth option.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="javascript">
{dedent`
const { Client } = require('@elastic/elasticsearch')
const client = new Client({
cloud: {
id: '${cloudId}',
},
auth: {
username: '<username>',
password: '<password>'
}
})`}
</EuiCodeBlock>
</>
) : (
<>
<EuiText>
<h4>Connecting to Elasticsearch</h4>
<p>
There are several ways to connect and authenticate to Elasticsearch running outside of
Cloud, including API keys, bearer tokens, and basic authentication.{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsJsClientConnecting}>
Visit the clients documentation to learn more
</a>
.
</p>
</EuiText>
</>
)}
</>
);
};

View file

@ -1,113 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchPhp: React.FC<{ cloudId?: string }> = ({ cloudId }) => {
return (
<>
<EuiText>
<p>
This official PHP client for Elasticsearch is designed to be a low-level client that does
not stray from the Elasticsearch REST API.
</p>
<EuiLink target="_blank" href={docLinks.clientsPhpOverview}>
Learn more about the official PHP client for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-php">
The official PHP client for Elasticsearch on Github
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>To install the latest version of the client, run the following command:</p>
<p>Elasticsearch-php only has four requirements that you need to pay attention:</p>
<ul>
<li>PHP 7.1.0 or higher</li>
<li>
<a target="_blank" rel="noopener" href="http://getcomposer.org/">
Composer
</a>
</li>
<li>
<a target="_blank" rel="noopener" href="http://php.net/manual/en/book.curl.php">
ext-curl
</a>
: the Libcurl extension for PHP
</li>
<li>Native JSON Extensions (ext-json) 1.3.7 or higher</li>
</ul>
<p>
The rest of the dependencies are automatically downloaded and installed by Composer.
Composer is a package and dependency manager for PHP and makes it easy to install
Elasticsearch-php.
</p>
<a target="_blank" rel="noopener" href={docLinks.clientsPhpInstallation}>
Visit the documentation for more information.
</a>
</EuiText>
<EuiSpacer />
{cloudId ? (
<>
<EuiText>
<h4>Connecting to Elastic Cloud</h4>
<p>
You can connect to Elastic Cloud using <strong>Basic authentication</strong> or an{' '}
<strong>API key</strong>. Where {'<cloud-id>'} is reported in the Deployment UI. For
basic authentication, {'<username>'} and {'<password>'} are generated when you deploy
a new cloud instance. Youll need to store the {'<username>'} and {'<password>'} since
they will not be available via UI.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="php">
{dedent`
// Connect via basic authentication
$client = ClientBuilder::create()
->setElasticCloudId('${cloudId}')
->setBasicAuthentication('<username>', '<password>')
->build();
// Connect with an API key
$client = ClientBuilder::create()
->setElasticCloudId('${cloudId}')
->setApiKey('<id>', '<key>')
->build();
`}
</EuiCodeBlock>
</>
) : (
<>
<EuiText>
<h4>Connecting to Elasticsearch</h4>
<p>
There are several ways to connect and authenticate to Elasticsearch running outside of
Cloud, including API keys, bearer tokens, and basic authentication.{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsPhpConnecting}>
Visit the clients documentation to learn more
</a>
.
</p>
</EuiText>
</>
)}
</>
);
};

View file

@ -1,163 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchPython: React.FC<{ cloudId?: string }> = ({ cloudId }) => {
return (
<>
<EuiText>
<p>
elasticsearch-py, the official Python client for Elasticsearch, is a low-level client for
interacting with Elasticsearchs REST API. Its designed to be unopinionated and
extendable.
</p>
<EuiLink target="_blank" href={docLinks.clientsPythonOverview}>
Learn more about the Python client for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://elasticsearch-py.readthedocs.io/">
The Python client for Elasticsearch on Read the Docs
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-py">
elasticsearch-py on Github
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>
Install the <code>elasticsearch</code> package with{' '}
<a target="_blank" rel="noopener" href="https://pypi.org/project/elasticsearch">
pip
</a>
:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
{dedent`
$ python -m pip install elasticsearch
`}
</EuiCodeBlock>
<EuiSpacer />
<EuiText>
<p>
If your application uses async/await in Python you can install the client with the async
extra:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
{dedent`
$ python -m pip install elasticsearch[async]
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>
Learn more about{' '}
<a target="_blank" rel="noopener" href="https://pypi.org/project/elasticsearch">
using asyncio with this project
</a>
.
</p>
</EuiText>
<EuiSpacer />
{cloudId ? (
<>
<EuiText>
<h4>Connecting to Elastic Cloud</h4>
<p>
Cloud ID is an easy way to configure your client to work with your Elastic Cloud
deployment. Combine the cloud_id with either basic_auth or api_key to authenticate
with your Elastic Cloud deployment.
</p>
<p>
Using cloud_id enables TLS verification and HTTP compression by default and sets the
port to 443 unless otherwise overwritten via the port parameter or the port value
encoded within cloud_id. Using Cloud ID also disables sniffing as a proxy is in use.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="python">
{dedent`
from elasticsearch import Elasticsearch
es = Elasticsearch(
cloud_id="${cloudId}"
)
`}
</EuiCodeBlock>
</>
) : (
<>
<EuiText>
<h4>Connecting to Elasticsearch</h4>
<p>
A single node can be specified via a <code>scheme</code>, <code>host</code>,{' '}
<code>port</code>, and optional <code>path_prefix</code>. These values can either be
specified manually via a URL in a string, dictionary,
<code>NodeConfig</code>, or a list of these values. You must specify at least{' '}
<code>scheme</code>, <code>host</code> and <code>port</code>
for each node. All of the following are valid configurations:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="python">
{dedent`
from elasticsearch import Elasticsearch
# Single node via URL
es = Elasticsearch("http://localhost:9200")
# Multiple nodes via URL
es = Elasticsearch([
"http://localhost:9200",
"http://localhost:9201",
"http://localhost:9202"
])
# Single node via dictionary
es = Elasticsearch({"scheme": "http", "host": "localhost", "port": 9200})
# Multiple nodes via dictionary
es = Elasticsearch([
{"scheme": "http", "host": "localhost", "port": 9200},
{"scheme": "http", "host": "localhost", "port": 9201},
])
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>
There are several ways to authenticate to Elasticsearch running outside of Cloud,
including API keys, bearer tokens, and basic authentication.{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsPythonAuthentication}>
Visit the clients documentation to learn more
</a>
.
</p>
</EuiText>
</>
)}
</>
);
};

View file

@ -1,161 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchRuby: React.FC<{ cloudId?: string }> = ({ cloudId }) => {
return (
<>
<EuiText>
<p>
The <code>elasticsearch</code>{' '}
<a target="_blank" rel="noopener" href="http://rubygems.org/gems/elasticsearch">
Rubygem
</a>{' '}
provides a low-level client for communicating with an Elasticsearch cluster, fully
compatible with other official clients.
</p>
<EuiLink target="_blank" href={docLinks.clientsRubyOverview}>
Learn more about the Ruby client for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-ruby">
The Elasticsearch Ruby client on Github
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="http://rubydoc.info/gems/elasticsearch">
The Elasticsearch Ruby client on RubyDoc
</EuiLink>
<EuiSpacer />
<p>Check out these other official Ruby libraries for working with Elasticsearch:</p>
<ul>
<li>
<a
target="_blank"
rel="noopener"
href="https://github.com/elasticsearch/elasticsearch-rails"
>
elasticsearch-rails
</a>{' '}
- integration with Ruby models and Rails applications.
</li>
<li>
<a
target="_blank"
rel="noopener"
href="https://github.com/elastic/elasticsearch-ruby/tree/7.17/elasticsearch-extensions"
>
elasticsearch-extensions
</a>
, deprecated.
</li>
<li>
<a
target="_blank"
rel="noopener"
href="https://github.com/elastic/elasticsearch-dsl-ruby"
>
elasticsearch-dsl
</a>{' '}
which provides a Ruby API for the{' '}
<a target="_blank" rel="noopener" href={docLinks.queryDsl}>
Elasticsearch Query DSL
</a>
.
</li>
</ul>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>
Install the <code>elasticsearch</code> gem from Rubygems:
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="shell">
{dedent`
$ gem install elasticsearch
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>Or add it to your projects Gemfile:</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable>
{dedent`
gem 'elasticsearch', '<ELASTICSEARCH_VERSION>'
`}
</EuiCodeBlock>
<EuiSpacer />
{cloudId ? (
<>
<EuiText>
<h4>Connecting to Elastic Cloud</h4>
<p>
If you are using Elastic Cloud, the client offers an easy way to connect to it. You
must pass the Cloud ID that you can find in the cloud console.
</p>
<p>
You can connect to Elastic Cloud using <strong>Basic authentication</strong> or an{' '}
<strong>API key</strong>. Where {'<cloud-id>'} is reported in the Deployment UI. For
basic authentication, {'<username>'} and {'<password>'} are generated when you deploy
a new cloud instance. Youll need to store the {'<username>'} and {'<password>'} since
they will not be available via UI.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable language="ruby">
{dedent`
require 'elasticsearch'
// Connect via basic authentication
client = Elasticsearch::Client.new(
cloud_id: '${cloudId}'
user: '<Username>',
password: '<Password>',
)
// Connect via API key
client = Elasticsearch::Client.new(
cloud_id: '${cloudId}',
api_key: {id: '<Id>', api_key: '<APIKey>'}
)
`}
</EuiCodeBlock>
</>
) : (
<>
<EuiText>
<h4>Connecting to Elasticsearch</h4>
<p>
There are several ways to authenticate to Elasticsearch running outside of Cloud,
including API keys, bearer tokens, and basic authentication.{' '}
<a target="_blank" rel="noopener" href={docLinks.clientsRubyAuthentication}>
Visit the clients documentation to learn more
</a>
.
</p>
</EuiText>
</>
)}
</>
);
};

View file

@ -1,89 +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 dedent from 'dedent';
import { EuiCodeBlock, EuiLink, EuiText, EuiSpacer } from '@elastic/eui';
import { docLinks } from '../../../../shared/doc_links';
export const ElasticsearchRust: React.FC = () => {
return (
<>
<EuiText>
<p>
The official Rust client for Elasticsearch includes all the features you need to add
search to a Rust application:
</p>
<ul>
<li>Fluent builders for all Elasticsearch REST API endpoints</li>
<li>Persistent keep-alive connections</li>
<li>TLS support with system or custom certificates</li>
<li>Proxy support with authentication</li>
<li>Async support with Tokio</li>
</ul>
<EuiLink target="_blank" href={docLinks.clientsRustOverview}>
Learn more about the Rust client for Elasticsearch
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://github.com/elastic/elasticsearch-rs">
The official Rust client for Elasticsearch on Github
</EuiLink>
<EuiSpacer size="m" />
<EuiLink target="_blank" href="https://docs.rs/elasticsearch">
View the documentation on docs.rs
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiText>
<h4>Installation</h4>
<p>
Add <code>elasticsearch</code> crate and version to Cargo.toml.
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable>
{dedent`
[dependencies]
elasticsearch = "<ELASTICSEARCH_VERSION>"
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>
The following optional dependencies may also be useful to create requests and read
responses
</p>
</EuiText>
<EuiSpacer size="s" />
<EuiCodeBlock fontSize="m" isCopyable>
{dedent`
serde = "~1"
serde_json = "~1"
`}
</EuiCodeBlock>
<EuiSpacer size="s" />
<EuiText>
<p>
The client also includes{' '}
<a
target="_blank"
rel="noopener"
href="https://github.com/elastic/elasticsearch-rs#async-support-with-tokio"
>
async support with tokio
</a>
.
</p>
</EuiText>
</>
);
};

View file

@ -1,26 +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 { ElasticsearchDotnet } from './elasticsearch_dotnet';
import { ElasticsearchGo } from './elasticsearch_go';
import { ElasticsearchJava } from './elasticsearch_java';
import { ElasticsearchJavascript } from './elasticsearch_javascript';
import { ElasticsearchPhp } from './elasticsearch_php';
import { ElasticsearchPython } from './elasticsearch_python';
import { ElasticsearchRuby } from './elasticsearch_ruby';
import { ElasticsearchRust } from './elasticsearch_rust';
export {
ElasticsearchDotnet,
ElasticsearchGo,
ElasticsearchJava,
ElasticsearchJavascript,
ElasticsearchPhp,
ElasticsearchPython,
ElasticsearchRuby,
ElasticsearchRust,
};

View file

@ -1,99 +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 { setMockValues, mockTelemetryActions } from '../../../__mocks__/kea_logic';
import React from 'react';
import { shallow, ShallowWrapper } from 'enzyme';
import { EuiButtonIcon, EuiCopy, EuiFieldText } from '@elastic/eui';
import { ElasticsearchCloudId } from '.';
const execCommandMock = (global.document.execCommand = jest.fn());
const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
describe('Elasticsearch Cloud Id', () => {
let wrapper: ShallowWrapper;
beforeEach(() => {
setMockValues({
cloud: {
cloudId: 'example-cloud-id',
deploymentUrl: 'https://cloud.elastic.co/deployments/fake-deployment-id',
},
});
wrapper = shallow(<ElasticsearchCloudId />);
});
afterEach(() => {
jest.clearAllMocks();
});
describe('Visibility conditions', () => {
it('renders panel when cloud id is provided', () => {
expect(wrapper.find('[data-test-subj="CloudIdPanel"]')).toHaveLength(1);
});
it('is hidden when cloud id isnt available', () => {
setMockValues({ cloud: { cloudId: null } });
wrapper = shallow(<ElasticsearchCloudId />);
expect(wrapper.find('[data-test-subj="CloudIdPanel"]')).toHaveLength(0);
});
});
describe('Cloud Id Interactions', () => {
it('should be able copy cloud id', () => {
const field = wrapper.find(EuiFieldText).dive();
expect(field.props()).toEqual(
expect.objectContaining({
readOnly: true,
})
);
expect(field.find('input').props()).toEqual(
expect.objectContaining({
value: 'example-cloud-id',
})
);
const euiCopyHOC = field.dive().find(EuiCopy);
expect(euiCopyHOC.props().textToCopy).toEqual('example-cloud-id');
const copyButton = euiCopyHOC.dive().find(EuiButtonIcon);
expect(copyButton).toHaveLength(1);
execCommandMock.mockImplementationOnce(() => true);
copyButton.simulate('click');
expect(execCommandMock).toHaveBeenCalledWith('copy');
expect(mockTelemetryActions.sendEnterpriseSearchTelemetry).toHaveBeenCalledWith({
action: 'clicked',
metric: 'cloud_id',
});
});
it('should fail gracefully if not allowed to copy', () => {
const field = wrapper.find(EuiFieldText).dive();
const euiCopyHOC = field.dive().find(EuiCopy);
const copyButton = euiCopyHOC.dive().find(EuiButtonIcon);
execCommandMock.mockImplementationOnce(() => false);
copyButton.simulate('click');
expect(execCommandMock).toHaveBeenCalledWith('copy');
expect(warn).toHaveBeenCalledWith('Unable to copy to clipboard.');
expect(mockTelemetryActions.sendEnterpriseSearchTelemetry).toHaveBeenCalled();
});
it('should present a manage link to deployment screen', () => {
const manageLink = wrapper.find('[data-test-subj="cloudManageLink"]');
expect(manageLink).toHaveLength(1);
expect(manageLink.props().href).toEqual(
'https://cloud.elastic.co/deployments/fake-deployment-id'
);
});
});
});

View file

@ -1,136 +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 { useActions, useValues } from 'kea';
import {
EuiButton,
EuiButtonIcon,
EuiCopy,
EuiFieldText,
EuiFlexGroup,
EuiFlexItem,
EuiForm,
EuiFormRow,
EuiLink,
EuiPanel,
EuiTitle,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useCloudDetails } from '../../../shared/cloud_details/cloud_details';
import { HttpLogic } from '../../../shared/http';
import { TelemetryLogic } from '../../../shared/telemetry';
import { SendTelemetryHelper } from '../../../shared/telemetry/telemetry_logic';
const onFocusHandler = (e: React.FocusEvent<HTMLInputElement>): void => {
e.target.select();
};
const copyCloudIdHandler = (
copy: () => void,
sendTelemetry: ({ action, metric }: SendTelemetryHelper) => void
) => {
return () => {
copy();
sendTelemetry({
action: 'clicked',
metric: 'cloud_id',
});
};
};
export const ElasticsearchCloudId: React.FC = () => {
const cloud = useCloudDetails();
const { sendEnterpriseSearchTelemetry } = useActions(TelemetryLogic);
const { http } = useValues(HttpLogic);
// hide the panel when no cloud context is available
if (!cloud.cloudId) {
return null;
}
return (
<EuiPanel color="subdued" grow={false} data-test-subj="CloudIdPanel">
<EuiFlexGroup justifyContent="spaceBetween" alignItems="center" responsive>
<EuiFlexItem>
<EuiFlexGroup gutterSize="s" alignItems="center" responsive={false}>
<EuiFlexItem>
<EuiTitle size={'xs'}>
<h2>
{i18n.translate('xpack.enterpriseSearch.overview.elasticsearchCloudId.heading', {
defaultMessage: 'My Deployment',
})}
</h2>
</EuiTitle>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiLink href={cloud.deploymentUrl} target="_blank" data-test-subj="cloudManageLink">
{i18n.translate('xpack.enterpriseSearch.overview.elasticsearchCloudId.manageLink', {
defaultMessage: 'Manage',
})}
</EuiLink>
</EuiFlexItem>
</EuiFlexGroup>
<EuiFlexGroup direction="column" gutterSize="m">
<EuiFlexItem>
<EuiForm component="form">
<EuiFormRow
label={i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchCloudId.cloudIdLabel',
{
defaultMessage: 'Cloud ID',
}
)}
>
<EuiFieldText
onFocus={onFocusHandler}
value={cloud.cloudId}
compressed
readOnly
append={
<EuiCopy textToCopy={cloud.cloudId}>
{(copy) => (
<EuiButtonIcon
iconType={'copyClipboard'}
onClick={copyCloudIdHandler(copy, sendEnterpriseSearchTelemetry)}
iconSize="m"
data-test-subj="CopyCloudIdButton"
aria-label={i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchCloudId.copyCloudIdAriaLabel',
{
defaultMessage: 'Copy Cloud ID',
}
)}
/>
)}
</EuiCopy>
}
/>
</EuiFormRow>
</EuiForm>
</EuiFlexItem>
<EuiFlexItem>
<EuiButton href={`${http.basePath.publicBaseUrl}/app/management/security/api_keys`}>
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchCloudId.manageApiKeysLink',
{
defaultMessage: 'Manage API keys',
}
)}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
};

View file

@ -1,8 +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.
*/
export { ElasticsearchCloudId } from './elasticsearch_cloud_id';

View file

@ -1,73 +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 { shallow, ShallowWrapper } from 'enzyme';
import { EuiSteps, EuiSelect } from '@elastic/eui';
import { ElasticsearchClientInstructions } from '../elasticsearch_client_instructions';
import { ElasticsearchGuide } from '.';
describe('Elasticsearch Guide Component', () => {
let wrapper: ShallowWrapper;
const setup = (param: string) => {
Object.defineProperty(window, 'location', {
value: { search: param },
writable: true,
});
wrapper = shallow(<ElasticsearchGuide />);
};
describe('Rendering Language option ', () => {
it('should use default language (java)', () => {
setup('');
const clientInstructionsElement = wrapper
.find(EuiSteps)
.dive()
.find(ElasticsearchClientInstructions);
expect(clientInstructionsElement.prop('language')).toBe('java');
});
it('should use language from param (ruby)', () => {
setup('?client=ruby');
const clientInstructionsElement = wrapper
.find(EuiSteps)
.dive()
.find(ElasticsearchClientInstructions);
expect(clientInstructionsElement.prop('language')).toBe('ruby');
});
it('should fallback to java if client not recognised', () => {
setup('?client=coffeescript');
const clientInstructionsElement = wrapper
.find(EuiSteps)
.dive()
.find(ElasticsearchClientInstructions);
expect(clientInstructionsElement.prop('language')).toBe('java');
});
});
describe('Changing Language option', () => {
it('should change the client instructions language prop when choosing another option', () => {
setup('');
const languageSelectElement = wrapper.find(EuiSteps).dive().find(EuiSelect);
languageSelectElement.simulate('change', { target: { value: 'ruby' } });
wrapper.update();
const clientInstructionsElement = wrapper
.find(EuiSteps)
.dive()
.find(ElasticsearchClientInstructions);
expect(clientInstructionsElement.prop('language')).toBe('ruby');
});
});
});

View file

@ -7,191 +7,81 @@
import React, { useEffect, useState } from 'react';
import queryString from 'query-string';
import { useActions, useValues } from 'kea';
import {
EuiText,
EuiFlexGroup,
EuiFlexItem,
EuiSpacer,
EuiSteps,
EuiSelect,
EuiLink,
useGeneratedHtmlId,
} from '@elastic/eui';
import { EuiHorizontalRule, EuiSpacer, EuiText, EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { LanguageDefinitionSnippetArguments } from '@kbn/search-api-panels';
import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants';
import { docLinks } from '../../../shared/doc_links';
import { ElasticsearchResources } from '../../../shared/elasticsearch_resources';
import { SetElasticsearchChrome as SetPageChrome } from '../../../shared/kibana_chrome';
import { ElasticsearchClientInstructions } from '../elasticsearch_client_instructions';
import { ElasticsearchCloudId } from '../elasticsearch_cloud_id';
import { Status } from '../../../../../common/types/api';
import { CreateApiKeyAPILogic } from '../../../enterprise_search_overview/api/create_elasticsearch_api_key_logic';
import { FetchApiKeysAPILogic } from '../../../enterprise_search_overview/api/fetch_api_keys_logic';
import { CreateApiKeyFlyout } from '../../../shared/api_key/create_api_key_flyout';
import { useCloudDetails } from '../../../shared/cloud_details/cloud_details';
import { GettingStarted } from '../../../shared/getting_started/getting_started';
import { KibanaLogic } from '../../../shared/kibana/kibana_logic';
import { EnterpriseSearchElasticsearchPageTemplate } from '../layout';
// Replace FormattedMessage with i18n strings
export const ElasticsearchGuide = () => {
const { user } = useValues(KibanaLogic);
const cloudContext = useCloudDetails();
const [isFlyoutOpen, setIsFlyoutOpen] = useState(false);
export const ElasticsearchGuide: React.FC = () => {
const languages = [
{ value: 'dotnet', text: '.Net' },
{ value: 'go', text: 'Go' },
{ value: 'java', text: 'Java' },
{ value: 'javascript', text: 'JavaScript' },
{ value: 'php', text: 'PHP' },
{ value: 'python', text: 'Python' },
{ value: 'ruby', text: 'Ruby' },
{ value: 'rust', text: 'Rust' },
];
const client = queryString.parse(window.location.search).client as string;
const languageExists = languages.some((language) => language.value === client);
const [selectedLanguage, setSelectedLanguage] = useState(languageExists ? client : 'java');
const basicSelectId = useGeneratedHtmlId({ prefix: 'languageSelect' });
const onChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setSelectedLanguage(e.target.value);
const codeArgs: LanguageDefinitionSnippetArguments = {
apiKey: '',
cloudId: cloudContext.cloudId,
url: cloudContext.elasticsearchUrl || ELASTICSEARCH_URL_PLACEHOLDER,
};
const { makeRequest } = useActions(FetchApiKeysAPILogic);
const { makeRequest: saveApiKey } = useActions(CreateApiKeyAPILogic);
const { error, status } = useValues(CreateApiKeyAPILogic);
const { data } = useValues(FetchApiKeysAPILogic);
const apiKeys = data?.api_keys || [];
// TODO: The page keeps the scroll position if being opened from Enterpise Search Overview,
// This is a temporary solution for demoing
useEffect(() => {
window.scrollTo(0, 0);
}, []);
useEffect(() => makeRequest({}), []);
return (
<EnterpriseSearchElasticsearchPageTemplate>
<SetPageChrome />
<EuiFlexGroup alignItems="flexStart" data-test-subj="elasticsearchGuide">
{/* maxWidth is needed to prevent code blocks with long unbreakable strings (Kibana PR Cloud ID) from stretching the column */}
<EuiFlexItem grow={3} style={{ maxWidth: 800 }}>
<EuiText>
<h2>
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchTitle',
{
defaultMessage: 'Getting started with Elasticsearch',
}
)}
</h2>
<p>
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchDescription',
{
defaultMessage:
"Elasticsearch provides the low-level tools you need to build fast, relevant search for your website or application. Because it's powerful and flexible, Elasticsearch can handle search use cases of all shapes and sizes.",
}
)}
</p>
</EuiText>
<EuiSpacer />
<EuiSteps
headingElement="h2"
steps={[
{
title: i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchTitle',
{ defaultMessage: 'Connect to Elasticsearch' }
),
children: (
<>
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchDescription',
{
defaultMessage:
'Elastic builds and maintains clients in several popular languages and our community has contributed many more.',
}
)}
</p>
<EuiLink href={docLinks.clientsGuide} target="_blank">
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsLink',
{ defaultMessage: 'Learn more about Elasticsearch clients' }
)}
</EuiLink>
</EuiText>
<EuiSpacer />
<EuiSelect
prepend={i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectLabel',
{ defaultMessage: 'Select a client' }
)}
id={basicSelectId}
options={languages}
value={selectedLanguage}
onChange={(e) => onChange(e)}
aria-label={i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectAriaLabel',
{ defaultMessage: 'Language client' }
)}
/>
<EuiSpacer size="m" />
<ElasticsearchClientInstructions language={selectedLanguage} />
</>
),
},
{
title: i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceTitle',
{ defaultMessage: 'Build a search experience with Elasticsearch' }
),
children: (
<>
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceDescription',
{
defaultMessage:
'Ready to add an engaging, modern search experience to your application or website? Search UI, Elastics JavaScript search framework for building world-class search experiences, was made for the task.',
}
)}
</p>
</EuiText>
<EuiSpacer size="l" />
<EuiFlexGroup gutterSize="l" alignItems="center">
<EuiFlexItem grow={false}>
<EuiText>
<EuiLink
href="https://www.elastic.co/enterprise-search/search-ui"
target="_blank"
>
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIMarketingLink',
{ defaultMessage: 'Learn more about Search UI' }
)}
</EuiLink>
</EuiText>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiText>
<EuiLink href="https://github.com/elastic/search-ui" target="_blank">
{i18n.translate(
'xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIGitHubLink',
{ defaultMessage: 'Search UI on GitHub' }
)}
</EuiLink>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</>
),
},
]}
/>
</EuiFlexItem>
<EuiFlexItem grow={1}>
<ElasticsearchCloudId />
<EuiSpacer />
<ElasticsearchResources />
</EuiFlexItem>
</EuiFlexGroup>
{isFlyoutOpen && (
<CreateApiKeyFlyout
error={error?.body?.message}
isLoading={status === Status.LOADING}
onClose={() => setIsFlyoutOpen(false)}
setApiKey={saveApiKey}
username={user?.full_name || user?.username || ''}
/>
)}
<EuiTitle size="l" data-test-subj="elasticsearchGuide">
<h1>
{i18n.translate('xpack.enterpriseSearch.content.overview.gettingStarted.pageTitle', {
defaultMessage: 'Elasticsearch language clients',
})}
</h1>
</EuiTitle>
<EuiSpacer size="xl" />
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.pageDescription',
{
defaultMessage:
"Set up your programming language client, ingest some data, and you'll be ready to start searching within minutes.",
}
)}
</p>
</EuiText>
<EuiHorizontalRule />
<EuiSpacer />
<GettingStarted
apiKeys={apiKeys}
openApiKeyModal={() => setIsFlyoutOpen(true)}
codeArgs={codeArgs}
isPanelLeft
showPipelinesPanel
/>
</EnterpriseSearchElasticsearchPageTemplate>
);
};

View file

@ -1,8 +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.
*/
export { ElasticsearchGuide } from './elasticsearch_guide';

View file

@ -22,6 +22,7 @@ export const EnterpriseSearchElasticsearchPageTemplate: React.FC<PageTemplatePro
return (
<EnterpriseSearchPageTemplateWrapper
{...pageTemplateProps}
restrictWidth
solutionNav={{
name: ELASTICSEARCH_PLUGIN.NAME,
items: useEnterpriseSearchNav(),

View file

@ -11,7 +11,7 @@ import React from 'react';
import { shallow } from 'enzyme';
import { ElasticsearchGuide } from './components/elasticsearch_guide';
import { ElasticsearchGuide } from './components/elasticsearch_guide/elasticsearch_guide';
import { Elasticsearch } from '.';

View file

@ -13,7 +13,7 @@ import { isVersionMismatch } from '../../../common/is_version_mismatch';
import { InitialAppData } from '../../../common/types';
import { VersionMismatchPage } from '../shared/version_mismatch';
import { ElasticsearchGuide } from './components/elasticsearch_guide';
import { ElasticsearchGuide } from './components/elasticsearch_guide/elasticsearch_guide';
import { ROOT_PATH } from './routes';

View file

@ -5,65 +5,29 @@
* 2.0.
*/
import React, { useEffect, useState } from 'react';
import React, { useEffect } from 'react';
import { css } from '@emotion/react';
import dedent from 'dedent';
import { useActions, useValues } from 'kea';
import {
EuiButton,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiSpacer,
EuiSplitPanel,
EuiText,
EuiThemeProvider,
EuiTitle,
} from '@elastic/eui';
import { EuiTitle } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import {
SelectClientPanel,
LanguageDefinition,
LanguageDefinitionSnippetArguments,
LanguageClientPanel,
InstallClientPanel,
OverviewPanel,
CodeBox,
getLanguageDefinitionCodeSnippet,
getConsoleRequest,
} from '@kbn/search-api-panels';
import { LanguageDefinitionSnippetArguments } from '@kbn/search-api-panels';
import { PLUGIN_ID } from '../../../../../../../common/constants';
import { KibanaDeps } from '../../../../../../../common/types';
import { icons } from '../../../../../../assets/client_libraries';
import { useCloudDetails } from '../../../../../shared/cloud_details/cloud_details';
import { docLinks } from '../../../../../shared/doc_links';
import { HttpLogic } from '../../../../../shared/http';
import { KibanaLogic } from '../../../../../shared/kibana';
import { GettingStarted } from '../../../../../shared/getting_started/getting_started';
import { IndexViewLogic } from '../../index_view_logic';
import { OverviewLogic } from '../../overview.logic';
import { GenerateApiKeyModal } from '../generate_api_key_modal/modal';
import { consoleDefinition } from './languages/console';
import { curlDefinition } from './languages/curl';
import { languageDefinitions } from './languages/languages';
const DEFAULT_URL = 'https://localhost:9200';
export const APIGettingStarted = () => {
const { http } = useValues(HttpLogic);
const { apiKey, isGenerateModalOpen, indexPipelineParameters } = useValues(OverviewLogic);
const { fetchIndexPipelineParameters, openGenerateModal, closeGenerateModal } =
useActions(OverviewLogic);
const { indexName } = useValues(IndexViewLogic);
const { services } = useKibana<KibanaDeps>();
const cloudContext = useCloudDetails();
@ -83,9 +47,7 @@ export const APIGettingStarted = () => {
ingestPipeline: indexPipelineParameters.name,
url: cloudContext.elasticsearchUrl || DEFAULT_URL,
};
const assetBasePath = http.basePath.prepend(`/plugins/${PLUGIN_ID}/assets/client_libraries`);
const [selectedLanguage, setSelectedLanguage] = useState<LanguageDefinition>(curlDefinition);
return (
<>
{isGenerateModalOpen && (
@ -93,322 +55,12 @@ export const APIGettingStarted = () => {
)}
<EuiTitle size="l">
<h2>
{i18n.translate('xpack.enterpriseSearch.content.overview.gettingStarted.pageTitle', {
defaultMessage: 'Getting Started with Elastic API',
{i18n.translate('xpack.enterpriseSearch.gettingStarted.pageTitle', {
defaultMessage: 'Getting started with Elastic API',
})}
</h2>
</EuiTitle>
<SelectClientPanel
docLinks={{
elasticsearchClients: docLinks.clientsGuide,
kibanaRunApiInConsole: docLinks.consoleGuide,
}}
http={http}
isPanelLeft={false}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
>
{languageDefinitions.map((language, index) => (
<EuiFlexItem key={`panelItem.${index}`}>
<LanguageClientPanel
language={language}
setSelectedLanguage={setSelectedLanguage}
isSelectedLanguage={selectedLanguage === language}
src={icons[language.id]}
/>
</EuiFlexItem>
))}
</SelectClientPanel>
<InstallClientPanel
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'installClient', codeArgs)}
consoleRequest={getConsoleRequest('installClient')}
languages={languageDefinitions}
language={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
isPanelLeft={false}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.description',
{
defaultMessage:
"You'll need your private API key to securely connect to your project. Copy it somewhere safe.",
}
)}
rightPanelContent={
<EuiPanel>
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiTitle size="xs">
<h5>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeytitle',
{
defaultMessage: 'Generate an API key',
}
)}
</h5>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeydesc',
{
defaultMessage:
'Your private, unique identifier for authentication and authorization.',
}
)}
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup direction="row" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButton
key="viewApiKeys"
iconType="plusInCircle"
onClick={openGenerateModal}
fill
>
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.documementExample.generateApiKeyButton.createNew',
{ defaultMessage: 'New' }
)}
</p>
</EuiText>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
key="viewApiKeys"
iconType="popout"
iconSide="right"
onClick={() =>
KibanaLogic.values.navigateToUrl('/app/management/security/api_keys', {
shouldNotCreateHref: true,
})
}
>
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.documementExample.generateApiKeyButton.viewAll',
{ defaultMessage: 'Manage' }
)}
</p>
</EuiText>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.panelTitle',
{
defaultMessage: 'Generate an API key',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.description',
{
defaultMessage: "You'll need this to identify your deployment.",
}
)}
rightPanelContent={
<EuiSplitPanel.Outer>
<EuiSplitPanel.Inner>
<EuiTitle size="xs">
<h5>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.elasticTitle',
{
defaultMessage: 'Store your Elasticsearch URL',
}
)}
</h5>
</EuiTitle>
<EuiText>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.desc',
{
defaultMessage: 'Unique identifier for your deployment. ',
}
)}
</EuiText>
</EuiSplitPanel.Inner>
<EuiThemeProvider colorMode="dark">
<EuiSplitPanel.Inner paddingSize="none">
<EuiCodeBlock
isCopyable
fontSize="m"
// Code block isn't respecting overflow in only this situation
css={css`
overflow-wrap: anywhere;
`}
>
{codeArgs.cloudId
? dedent`{
CloudID: "${codeArgs.cloudId}",
Url: "${codeArgs.url}",
}`
: codeArgs.url}
</EuiCodeBlock>
</EuiSplitPanel.Inner>
</EuiThemeProvider>
</EuiSplitPanel.Outer>
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleElastic',
{
defaultMessage: 'Copy your Elasticsearch URL',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.configureClient.description',
{
defaultMessage: 'Initialize your client with your unique API key',
}
)}
rightPanelContent={
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(
selectedLanguage,
'configureClient',
codeArgs
)}
consoleRequest={getConsoleRequest('configureClient')}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.configureClient.title',
{
defaultMessage: 'Configure your client',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.testConnection.description',
{
defaultMessage:
'Send a test request to confirm your language client and Elasticsearch instance are up and running.',
}
)}
rightPanelContent={
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(
selectedLanguage,
'testConnection',
codeArgs
)}
consoleRequest={getConsoleRequest('testConnection')}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.testConnection.title',
{
defaultMessage: 'Test your connection',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.ingestData.description',
{
defaultMessage: 'Add data to your data stream or index to make it searchable',
}
)}
rightPanelContent={
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'ingestData', codeArgs)}
consoleRequest={getLanguageDefinitionCodeSnippet(
consoleDefinition,
'ingestData',
codeArgs
)}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
}
links={[]}
title={i18n.translate('xpack.enterpriseSearch.overview.gettingStarted.ingestData.title', {
defaultMessage: 'Ingest Data',
})}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.searchQuery.description',
{
defaultMessage:
"Now you're ready to start experimenting with searching and performing aggregations on your Elasticsearch data.",
}
)}
rightPanelContent={
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(
selectedLanguage,
'buildSearchQuery',
codeArgs
)}
consoleRequest={getLanguageDefinitionCodeSnippet(
consoleDefinition,
'buildSearchQuery',
codeArgs
)}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
}
links={[]}
title={i18n.translate('xpack.enterpriseSearch.overview.gettingStarted.searchQuery.title', {
defaultMessage: 'Build your first search query',
})}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<GettingStarted openApiKeyModal={openGenerateModal} codeArgs={codeArgs} />
</>
);
};

View file

@ -0,0 +1,335 @@
/*
* 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, { useState } from 'react';
import { useValues } from 'kea';
import { EuiButton, EuiFlexItem, EuiLink, EuiSpacer, EuiText } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { useKibana } from '@kbn/kibana-react-plugin/public';
import {
SelectClientPanel,
LanguageDefinition,
LanguageDefinitionSnippetArguments,
LanguageClientPanel,
InstallClientPanel,
OverviewPanel,
getLanguageDefinitionCodeSnippet,
getConsoleRequest,
CloudDetailsPanel,
} from '@kbn/search-api-panels';
import { ApiKey } from '@kbn/security-plugin/common';
import { PLUGIN_ID } from '../../../../common/constants';
import { KibanaDeps } from '../../../../common/types';
import { icons } from '../../../assets/client_libraries';
import { docLinks } from '../doc_links';
import { HttpLogic } from '../http';
import { curlDefinition } from './languages/curl';
import { languageDefinitions } from './languages/languages';
import { AddDataPanelContent } from './panels/add_data_panel_content';
import { ApiKeyPanelContent } from './panels/api_key_panel_content';
import { InitializeClientPanelContent } from './panels/initialize_client_panel_content';
import { GettingStartedPipelinePanel } from './panels/pipeline_panel';
import { SearchQueryPanelContent } from './panels/search_query_panel_content';
import { TestConnectionPanelContent } from './panels/test_connection_panel_content';
interface GettingStartedProps {
apiKeys?: ApiKey[];
codeArgs: LanguageDefinitionSnippetArguments;
isPanelLeft?: boolean;
openApiKeyModal: () => void;
showPipelinesPanel?: boolean;
}
export const GettingStarted: React.FC<GettingStartedProps> = ({
apiKeys,
codeArgs,
isPanelLeft = false,
openApiKeyModal,
showPipelinesPanel,
}) => {
const { http } = useValues(HttpLogic);
const { services } = useKibana<KibanaDeps>();
const assetBasePath = http.basePath.prepend(`/plugins/${PLUGIN_ID}/assets/client_libraries`);
const [selectedLanguage, setSelectedLanguage] = useState<LanguageDefinition>(curlDefinition);
return (
<>
<SelectClientPanel
docLinks={{
elasticsearchClients: docLinks.clientsGuide,
kibanaRunApiInConsole: docLinks.consoleGuide,
}}
http={http}
isPanelLeft={isPanelLeft}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
>
{languageDefinitions.map((language, index) => (
<EuiFlexItem key={`panelItem.${index}`}>
<LanguageClientPanel
language={language}
setSelectedLanguage={setSelectedLanguage}
isSelectedLanguage={selectedLanguage === language}
src={icons[language.id]}
/>
</EuiFlexItem>
))}
</SelectClientPanel>
<InstallClientPanel
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'installClient', codeArgs)}
consoleRequest={getConsoleRequest('installClient')}
languages={languageDefinitions}
language={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
isPanelLeft={isPanelLeft}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.description',
{
defaultMessage:
"You'll need your private API key to securely connect to your project. Copy it somewhere safe.",
}
)}
leftPanelContent={
isPanelLeft ? (
<ApiKeyPanelContent apiKeys={apiKeys} openApiKeyModal={openApiKeyModal} />
) : undefined
}
rightPanelContent={
isPanelLeft ? undefined : (
<ApiKeyPanelContent apiKeys={apiKeys} openApiKeyModal={openApiKeyModal} />
)
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.panelTitle',
{
defaultMessage: 'Generate an API key',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<CloudDetailsPanel
cloudId={codeArgs.cloudId}
elasticsearchUrl={codeArgs.url}
isPanelLeft={isPanelLeft}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.configureClient.description',
{
defaultMessage: 'Initialize your client with your unique API key',
}
)}
leftPanelContent={
isPanelLeft ? (
<InitializeClientPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
) : undefined
}
rightPanelContent={
isPanelLeft ? undefined : (
<InitializeClientPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
)
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.configureClient.title',
{
defaultMessage: 'Configure your client',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.testConnection.description',
{
defaultMessage:
'Send a test request to confirm your language client and Elasticsearch instance are up and running.',
}
)}
leftPanelContent={
isPanelLeft ? (
<TestConnectionPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
) : undefined
}
rightPanelContent={
isPanelLeft ? undefined : (
<TestConnectionPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
)
}
links={[]}
title={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.testConnection.title',
{
defaultMessage: 'Test your connection',
}
)}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.ingestData.description',
{
defaultMessage: 'Add data to your data stream or index to make it searchable',
}
)}
leftPanelContent={
isPanelLeft ? (
<AddDataPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
) : undefined
}
rightPanelContent={
isPanelLeft ? undefined : (
<AddDataPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
)
}
links={[]}
title={i18n.translate('xpack.enterpriseSearch.overview.gettingStarted.ingestData.title', {
defaultMessage: 'Ingest Data',
})}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
<OverviewPanel
description={i18n.translate(
'xpack.enterpriseSearch.overview.gettingStarted.searchQuery.description',
{
defaultMessage:
"Now you're ready to start experimenting with searching and performing aggregations on your Elasticsearch data.",
}
)}
leftPanelContent={
isPanelLeft ? (
<SearchQueryPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
) : undefined
}
rightPanelContent={
isPanelLeft ? undefined : (
<SearchQueryPanelContent
assetBasePath={assetBasePath}
codeArgs={codeArgs}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
/>
)
}
links={[]}
title={i18n.translate('xpack.enterpriseSearch.overview.gettingStarted.searchQuery.title', {
defaultMessage: 'Build your first search query',
})}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
/>
{showPipelinesPanel && (
<OverviewPanel
description={
<>
<FormattedMessage
id="xpack.enterpriseSearch.gettingStarted.pipeline.description"
defaultMessage="Use {ingestPipelinesLink} to preprocess your data before it's indexed into Elasticsearch, which is often much easier than post-processing. Use any combination of ingest processors to add, delete, or transform fields in your documents."
values={{
ingestPipelinesLink: (
<EuiLink
data-test-subj="enterpriseSearchElasticsearchOverviewIngestPipelinesLink"
href={docLinks.ingestPipelines}
target="_blank"
>
{i18n.translate(
'xpack.enterpriseSearch.gettingStarted.description.ingestPipelinesLink.link',
{
defaultMessage: 'ingest pipelines',
}
)}
</EuiLink>
),
}}
/>
<EuiSpacer />
<EuiButton
iconType="plusInCircle"
size="s"
href={http.basePath.prepend('/app/management/ingest/ingest_pipelines/create')}
data-telemetry-id="entSearch-gettingStarted-createPipeline"
data-test-subj="create-a-pipeline-button"
>
<EuiText size="s">
{i18n.translate(
'xpack.enterpriseSearch.gettingStarted.pipeline.description.createButtonLabel',
{
defaultMessage: 'Create a pipeline',
}
)}
</EuiText>
</EuiButton>
</>
}
leftPanelContent={<GettingStartedPipelinePanel />}
links={[]}
overviewPanelProps={{ color: 'plain', hasShadow: false }}
title={i18n.translate('xpack.enterpriseSearch.pipeline.title', {
defaultMessage: 'Transform and enrich your data',
})}
/>
)}
</>
);
};

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { Languages, LanguageDefinition } from '@kbn/search-api-panels';
import { docLinks } from '../../../../../../shared/doc_links';
import { docLinks } from '../../doc_links';
import { ingestKeysToJSON } from './helpers';

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { Languages, LanguageDefinition } from '@kbn/search-api-panels';
import { docLinks } from '../../../../../../shared/doc_links';
import { docLinks } from '../../doc_links';
import { ingestKeysToJSON } from './helpers';

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { Languages, LanguageDefinition } from '@kbn/search-api-panels';
import { docLinks } from '../../../../../../shared/doc_links';
import { docLinks } from '../../doc_links';
import { ingestKeysToJSON } from './helpers';

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { Languages, LanguageDefinition } from '@kbn/search-api-panels';
import { docLinks } from '../../../../../../shared/doc_links';
import { docLinks } from '../../doc_links';
import { ingestKeysToPHP } from './helpers';

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { Languages, LanguageDefinition } from '@kbn/search-api-panels';
import { docLinks } from '../../../../../../shared/doc_links';
import { docLinks } from '../../doc_links';
import { ingestKeysToJSON } from './helpers';

View file

@ -8,7 +8,7 @@
import { i18n } from '@kbn/i18n';
import { Languages, LanguageDefinition } from '@kbn/search-api-panels';
import { docLinks } from '../../../../../../shared/doc_links';
import { docLinks } from '../../doc_links';
import { ingestKeysToRuby } from './helpers';

View file

@ -0,0 +1,49 @@
/*
* 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 { useKibana } from '@kbn/kibana-react-plugin/public';
import {
CodeBox,
getConsoleRequest,
getLanguageDefinitionCodeSnippet,
LanguageDefinition,
LanguageDefinitionSnippetArguments,
} from '@kbn/search-api-panels';
import { KibanaDeps } from '../../../../../common/types';
import { languageDefinitions } from '../languages/languages';
interface AddDataPanelContentProps {
assetBasePath: string;
codeArgs: LanguageDefinitionSnippetArguments;
selectedLanguage: LanguageDefinition;
setSelectedLanguage: (selectedLanguage: LanguageDefinition) => void;
}
export const AddDataPanelContent: React.FC<AddDataPanelContentProps> = ({
assetBasePath,
codeArgs,
selectedLanguage,
setSelectedLanguage,
}) => {
const { services } = useKibana<KibanaDeps>();
return (
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'testConnection', codeArgs)}
consoleRequest={getConsoleRequest('testConnection')}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
);
};

View file

@ -0,0 +1,129 @@
/*
* 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 {
EuiPanel,
EuiFlexGroup,
EuiFlexItem,
EuiTitle,
EuiSpacer,
EuiText,
EuiButton,
EuiBadge,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { ApiKey } from '@kbn/security-plugin/common';
import { KibanaLogic } from '../../kibana';
interface ApiKeyPanelContent {
apiKeys?: ApiKey[];
openApiKeyModal: () => void;
}
export const ApiKeyPanelContent: React.FC<ApiKeyPanelContent> = ({ apiKeys, openApiKeyModal }) => {
return (
<EuiPanel>
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiTitle size="xs">
<h5>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeytitle',
{
defaultMessage: 'Generate an API key',
}
)}
</h5>
</EuiTitle>
<EuiSpacer size="s" />
<EuiText>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeydesc',
{
defaultMessage:
'Your private, unique identifier for authentication and authorization.',
}
)}
</EuiText>
</EuiFlexItem>
<EuiFlexItem>
<EuiFlexGroup alignItems="center" justifyContent="spaceBetween" direction="row">
<EuiFlexItem>
<EuiFlexGroup direction="row" gutterSize="s">
<EuiFlexItem grow={false}>
<EuiButton
key="viewApiKeys"
iconType="plusInCircle"
onClick={openApiKeyModal}
fill
>
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.documementExample.generateApiKeyButton.createNew',
{ defaultMessage: 'New' }
)}
</p>
</EuiText>
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
key="viewApiKeys"
iconType="popout"
iconSide="right"
onClick={() =>
KibanaLogic.values.navigateToUrl('/app/management/security/api_keys', {
shouldNotCreateHref: true,
})
}
>
<EuiText>
<p>
{i18n.translate(
'xpack.enterpriseSearch.content.overview.documementExample.generateApiKeyButton.viewAll',
{ defaultMessage: 'Manage' }
)}
</p>
</EuiText>
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiFlexGroup gutterSize="s">
<EuiFlexItem>
<EuiText size="xs" color="subdued">
<FormattedMessage
id="xpack.enterpriseSearch.apiKey.activeKeys"
defaultMessage="{number} active API keys."
values={{
number: (
<EuiBadge
color={(apiKeys?.length || 0) > 0 ? 'success' : 'warning'}
data-test-subj="api-keys-count-badge"
>
{apiKeys?.length || 0}
</EuiBadge>
),
}}
/>
</EuiText>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
</EuiPanel>
);
};

View file

@ -0,0 +1,49 @@
/*
* 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 { useKibana } from '@kbn/kibana-react-plugin/public';
import {
CodeBox,
getConsoleRequest,
getLanguageDefinitionCodeSnippet,
LanguageDefinition,
LanguageDefinitionSnippetArguments,
} from '@kbn/search-api-panels';
import { KibanaDeps } from '../../../../../common/types';
import { languageDefinitions } from '../languages/languages';
interface InitializeClientPanelContentProps {
assetBasePath: string;
codeArgs: LanguageDefinitionSnippetArguments;
selectedLanguage: LanguageDefinition;
setSelectedLanguage: (selectedLanguage: LanguageDefinition) => void;
}
export const InitializeClientPanelContent: React.FC<InitializeClientPanelContentProps> = ({
assetBasePath,
codeArgs,
selectedLanguage,
setSelectedLanguage,
}) => {
const { services } = useKibana<KibanaDeps>();
return (
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'configureClient', codeArgs)}
consoleRequest={getConsoleRequest('configureClient')}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
);
};

View file

@ -0,0 +1,20 @@
/*
* 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 { PipelinePanel } from '@kbn/search-api-panels';
import clusterImage from '../../../../assets/images/cluster.svg';
import cutImage from '../../../../assets/images/cut.svg';
import reporterImage from '../../../../assets/images/reporter.svg';
export const GettingStartedPipelinePanel: React.FC = () => {
return (
<PipelinePanel clusterImage={clusterImage} cutImage={cutImage} reporterImage={reporterImage} />
);
};

View file

@ -0,0 +1,53 @@
/*
* 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 { useKibana } from '@kbn/kibana-react-plugin/public';
import {
CodeBox,
getLanguageDefinitionCodeSnippet,
LanguageDefinition,
LanguageDefinitionSnippetArguments,
} from '@kbn/search-api-panels';
import { KibanaDeps } from '../../../../../common/types';
import { consoleDefinition } from '../languages/console';
import { languageDefinitions } from '../languages/languages';
interface SearchQueryPanelContentProps {
assetBasePath: string;
codeArgs: LanguageDefinitionSnippetArguments;
selectedLanguage: LanguageDefinition;
setSelectedLanguage: (selectedLanguage: LanguageDefinition) => void;
}
export const SearchQueryPanelContent: React.FC<SearchQueryPanelContentProps> = ({
assetBasePath,
codeArgs,
selectedLanguage,
setSelectedLanguage,
}) => {
const { services } = useKibana<KibanaDeps>();
return (
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'buildSearchQuery', codeArgs)}
consoleRequest={getLanguageDefinitionCodeSnippet(
consoleDefinition,
'buildSearchQuery',
codeArgs
)}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
);
};

View file

@ -0,0 +1,49 @@
/*
* 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 { useKibana } from '@kbn/kibana-react-plugin/public';
import {
CodeBox,
getConsoleRequest,
getLanguageDefinitionCodeSnippet,
LanguageDefinition,
LanguageDefinitionSnippetArguments,
} from '@kbn/search-api-panels';
import { KibanaDeps } from '../../../../../common/types';
import { languageDefinitions } from '../languages/languages';
interface TestConnectionPanelContentProps {
assetBasePath: string;
codeArgs: LanguageDefinitionSnippetArguments;
selectedLanguage: LanguageDefinition;
setSelectedLanguage: (selectedLanguage: LanguageDefinition) => void;
}
export const TestConnectionPanelContent: React.FC<TestConnectionPanelContentProps> = ({
assetBasePath,
codeArgs,
selectedLanguage,
setSelectedLanguage,
}) => {
const { services } = useKibana<KibanaDeps>();
return (
<CodeBox
languages={languageDefinitions}
codeSnippet={getLanguageDefinitionCodeSnippet(selectedLanguage, 'testConnection', codeArgs)}
consoleRequest={getConsoleRequest('testConnection')}
selectedLanguage={selectedLanguage}
setSelectedLanguage={setSelectedLanguage}
assetBasePath={assetBasePath}
application={services.application}
sharePlugin={services.share}
/>
);
};

View file

@ -27,33 +27,31 @@ import {
EuiHorizontalRule,
EuiButton,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { FormattedMessage, I18nProvider } from '@kbn/i18n-react';
import { ELASTICSEARCH_URL_PLACEHOLDER } from '@kbn/search-api-panels/constants';
import { Status } from '../../../../common/types/api';
import endpointIcon from '../../../assets/images/endpoint_icon.svg';
import { CreateApiKeyAPILogic } from '../../enterprise_search_overview/api/create_elasticsearch_api_key_logic';
import { FetchApiKeysAPILogic } from '../../enterprise_search_overview/api/fetch_api_keys_logic';
import { CreateApiKeyFlyout } from '../api_key/create_api_key_flyout';
import { KibanaLogic } from '../kibana';
interface EndpointsHeaderActionProps {
isFlyoutOpen: boolean;
setIsFlyoutOpen: (isOpen: boolean) => void;
}
export const EndpointsHeaderAction: React.FC<EndpointsHeaderActionProps> = ({
setIsFlyoutOpen,
}) => {
export const EndpointsHeaderAction: React.FC = () => {
const [isPopoverOpen, setPopoverOpen] = useState(false);
const { cloud, navigateToUrl } = useValues(KibanaLogic);
const { makeRequest } = useActions(FetchApiKeysAPILogic);
const { data } = useValues(FetchApiKeysAPILogic);
const [isFlyoutOpen, setIsFlyoutOpen] = useState(false);
const { user } = useValues(KibanaLogic);
const { makeRequest: saveApiKey } = useActions(CreateApiKeyAPILogic);
const { data: apiKey, error, status } = useValues(CreateApiKeyAPILogic);
useEffect(() => makeRequest({}), []);
if (!cloud) {
return null;
}
const COPIED_LABEL = i18n.translate('xpack.enterpriseSearch.pageTemplate.apiKey.copied', {
defaultMessage: 'Copied',
});
@ -76,7 +74,17 @@ export const EndpointsHeaderAction: React.FC<EndpointsHeaderActionProps> = ({
);
return (
<>
<I18nProvider>
{isFlyoutOpen && (
<CreateApiKeyFlyout
createdApiKey={apiKey}
error={error?.body?.message}
isLoading={status === Status.LOADING}
onClose={() => setIsFlyoutOpen(false)}
setApiKey={saveApiKey}
username={user?.full_name || user?.username || ''}
/>
)}
<EuiPopover
button={button}
isOpen={isPopoverOpen}
@ -119,36 +127,40 @@ export const EndpointsHeaderAction: React.FC<EndpointsHeaderActionProps> = ({
</EuiFlexItem>
</EuiFlexGroup>
</EuiContextMenuItem>,
<EuiContextMenuItem key="cloudId">
<EuiText size="s">
{i18n.translate('xpack.enterpriseSearch.apiKey.cloudId', {
defaultMessage: 'Cloud ID:',
})}
</EuiText>
<EuiSpacer size="s" />
...(Boolean(cloudId)
? [
<EuiContextMenuItem key="cloudId">
<EuiText size="s">
{i18n.translate('xpack.enterpriseSearch.apiKey.cloudId', {
defaultMessage: 'Cloud ID:',
})}
</EuiText>
<EuiSpacer size="s" />
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd" alignItems="center">
<EuiFlexItem>
<EuiCode>{cloudId}</EuiCode>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiCopy textToCopy={cloudId || ''} afterMessage={COPIED_LABEL}>
{(copy) => (
<EuiButtonIcon
onClick={copy}
iconType="copyClipboard"
aria-label={i18n.translate(
'xpack.enterpriseSearch.overview.apiKey.copyCloudID',
{
defaultMessage: 'Copy cloud ID to clipboard.',
}
)}
/>
)}
</EuiCopy>
</EuiFlexItem>
</EuiFlexGroup>
</EuiContextMenuItem>,
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd" alignItems="center">
<EuiFlexItem>
<EuiCode>{cloudId}</EuiCode>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiCopy textToCopy={cloudId || ''} afterMessage={COPIED_LABEL}>
{(copy) => (
<EuiButtonIcon
onClick={copy}
iconType="copyClipboard"
aria-label={i18n.translate(
'xpack.enterpriseSearch.overview.apiKey.copyCloudID',
{
defaultMessage: 'Copy cloud ID to clipboard.',
}
)}
/>
)}
</EuiCopy>
</EuiFlexItem>
</EuiFlexGroup>
</EuiContextMenuItem>,
]
: []),
<EuiContextMenuItem key="apiKeys">
<EuiFlexGroup gutterSize="s" justifyContent="flexEnd" alignItems="center">
<EuiFlexItem>
@ -192,7 +204,10 @@ export const EndpointsHeaderAction: React.FC<EndpointsHeaderActionProps> = ({
<EuiButton
iconType="plusInCircle"
size="s"
onClick={() => setIsFlyoutOpen(true)}
onClick={() => {
setIsFlyoutOpen(true);
setPopoverOpen(false);
}}
data-test-subj="new-api-key-button"
fullWidth
>
@ -206,6 +221,6 @@ export const EndpointsHeaderAction: React.FC<EndpointsHeaderActionProps> = ({
]}
/>
</EuiPopover>
</>
</I18nProvider>
);
};

View file

@ -5,22 +5,17 @@
* 2.0.
*/
import React, { useState } from 'react';
import React, { useEffect } from 'react';
import classNames from 'classnames';
import { useActions, useValues } from 'kea';
import { useValues } from 'kea';
import { EuiCallOut, EuiSpacer } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n-react';
import { KibanaPageTemplate, KibanaPageTemplateProps } from '@kbn/shared-ux-page-kibana-template';
import { Status } from '../../../../common/types/api';
import { CreateApiKeyAPILogic } from '../../enterprise_search_overview/api/create_elasticsearch_api_key_logic';
import { CreateApiKeyFlyout } from '../api_key/create_api_key_flyout';
import { FlashMessages } from '../flash_messages';
import { HttpLogic } from '../http';
import { KibanaLogic } from '../kibana';
@ -69,25 +64,18 @@ export const EnterpriseSearchPageTemplateWrapper: React.FC<PageTemplateProps> =
...pageTemplateProps
}) => {
const { readOnlyMode } = useValues(HttpLogic);
const { cloud, renderHeaderActions, user } = useValues(KibanaLogic);
const { makeRequest: saveApiKey } = useActions(CreateApiKeyAPILogic);
const { data: apiKey, error, status } = useValues(CreateApiKeyAPILogic);
const { renderHeaderActions } = useValues(KibanaLogic);
const hasCustomEmptyState = !!emptyState;
const showCustomEmptyState = hasCustomEmptyState && isEmptyState;
const navIcon = solutionNavIcon ?? 'logoEnterpriseSearch';
const [isFlyoutOpen, setIsFlyoutOpen] = useState(false);
const HeaderAction: React.FC<{}> = () => (
<I18nProvider>
<EndpointsHeaderAction isFlyoutOpen={isFlyoutOpen} setIsFlyoutOpen={setIsFlyoutOpen} />
</I18nProvider>
);
if (cloud && useEndpointHeaderActions) {
renderHeaderActions(HeaderAction);
}
useEffect(() => {
if (useEndpointHeaderActions) {
renderHeaderActions(EndpointsHeaderAction);
}
}, []);
return (
<KibanaPageTemplate
restrictWidth={false}
@ -103,16 +91,6 @@ export const EnterpriseSearchPageTemplateWrapper: React.FC<PageTemplateProps> =
isEmptyState={isEmptyState && !isLoading}
solutionNav={solutionNav && solutionNav.items ? { icon: navIcon, ...solutionNav } : undefined}
>
{isFlyoutOpen && (
<CreateApiKeyFlyout
createdApiKey={apiKey}
error={error?.body?.message}
isLoading={status === Status.LOADING}
onClose={() => setIsFlyoutOpen(false)}
setApiKey={saveApiKey}
username={user?.full_name || user?.username || ''}
/>
)}
{setPageChrome}
{readOnlyMode && (
<>

View file

@ -0,0 +1,4 @@
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="56" height="56" rx="28" fill="#79AAD9"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.25 10.5C23.6581 10.5 27.3049 13.7596 27.9114 18H35.7134C36.2282 16.5435 37.6172 15.5 39.25 15.5C41.3211 15.5 43 17.1789 43 19.25C43 21.3211 41.3211 23 39.25 23C37.6172 23 36.2282 21.9565 35.7134 20.5H27.9114C27.6993 21.9824 27.1157 23.345 26.2579 24.4903L31.5095 29.7423C32.9702 28.6481 34.7844 28 36.75 28C41.5825 28 45.5 31.9175 45.5 36.75C45.5 41.5825 41.5825 45.5 36.75 45.5C32.3419 45.5 28.6951 42.2404 28.0886 38H20.2866C19.7718 39.4565 18.3828 40.5 16.75 40.5C14.6789 40.5 13 38.8211 13 36.75C13 34.6789 14.6789 33 16.75 33C18.3828 33 19.7718 34.0435 20.2866 35.5H28.0886C28.3006 34.0178 28.8841 32.6554 29.7418 31.5101L24.4902 26.258C23.0294 27.352 21.2154 28 19.25 28C14.4175 28 10.5 24.0825 10.5 19.25C10.5 14.4175 14.4175 10.5 19.25 10.5ZM19.25 25.5C22.7018 25.5 25.5 22.7018 25.5 19.25C25.5 15.7982 22.7018 13 19.25 13C15.7982 13 13 15.7982 13 19.25C13 22.7018 15.7982 25.5 19.25 25.5ZM38 19.25C38 19.9404 38.5596 20.5 39.25 20.5C39.9404 20.5 40.5 19.9404 40.5 19.25C40.5 18.5596 39.9404 18 39.25 18C38.5596 18 38 18.5596 38 19.25ZM36.75 43C33.2982 43 30.5 40.2018 30.5 36.75C30.5 33.2982 33.2982 30.5 36.75 30.5C40.2018 30.5 43 33.2982 43 36.75C43 40.2018 40.2018 43 36.75 43ZM18 36.75C18 37.4404 17.4404 38 16.75 38C16.0596 38 15.5 37.4404 15.5 36.75C15.5 36.0596 16.0596 35.5 16.75 35.5C17.4404 35.5 18 36.0596 18 36.75Z" fill="#4A7194"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1,11 @@
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="56" height="56" rx="28" fill="#6DCCB1"/>
<g clip-path="url(#clip0_1564_106662)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20.8557 35.6855L16.0761 37.0561C12.7157 38.0196 9.21041 36.0766 8.24684 32.7162C7.28326 29.3558 9.22626 25.8506 12.5867 24.887L17.4543 23.4912C19.8262 22.8111 22.2704 23.5791 23.8419 25.2715L27.666 11.9351C28.0138 10.7221 29.1657 9.69248 30.5642 8.84101C31.2405 8.42924 31.8652 8.14614 32.5122 8.04084C34.5463 7.70982 36.2699 9.43566 35.6654 11.5949L31.9342 24.607L44.4051 21.0311C46.5643 20.4265 48.2902 22.1501 47.9592 24.1842C47.8539 24.8312 47.5708 25.4559 47.159 26.1322C46.3075 27.5307 45.2779 28.6826 44.0649 29.0304L31.8073 32.5452C33.2293 34.1142 33.8318 36.3606 33.2052 38.5457L31.8094 43.4133C30.8459 46.7737 27.3406 48.7167 23.9802 47.7532C20.6198 46.7896 18.6768 43.2843 19.6404 39.9239L20.8557 35.6855ZM21.6786 32.8156L22.878 28.633C22.8691 28.5983 22.8597 28.5636 22.8497 28.5289C22.2716 26.5127 20.1684 25.3469 18.1522 25.925L13.2845 27.3208C11.2683 27.899 10.1025 30.0021 10.6806 32.0184C11.2588 34.0346 13.362 35.2004 15.3782 34.6223L21.6786 32.8156ZM31.1113 27.4769L30.2883 30.3468L43.3671 26.5966C44.1783 26.3639 46.3221 23.1236 45.103 23.4649L31.1113 27.4769ZM22.0742 40.6218C21.496 42.638 22.6618 44.7412 24.6781 45.3194C26.6943 45.8975 28.7975 44.7317 29.3756 42.7155L30.7714 37.8478C31.3495 35.8316 30.1837 33.7284 28.1675 33.1503C27.7408 33.0279 27.3102 32.9837 26.891 33.0091L33.2316 10.897C33.5728 9.67792 30.3325 11.8217 30.0999 12.6329L22.0742 40.6218ZM24.508 41.3197L25.9038 36.4521C26.0965 35.78 26.7975 35.3914 27.4696 35.5841C28.1417 35.7768 28.5303 36.4779 28.3376 37.1499L26.9418 42.0176C26.7491 42.6897 26.048 43.0783 25.376 42.8855C24.7039 42.6928 24.3153 41.9918 24.508 41.3197ZM14.6803 32.1884C14.0082 32.3812 13.3072 31.9926 13.1145 31.3205C12.9217 30.6484 13.3103 29.9473 13.9824 29.7546L18.8501 28.3589C19.5221 28.1661 20.2232 28.5547 20.4159 29.2268C20.6086 29.8989 20.22 30.6 19.5479 30.7927L14.6803 32.1884Z" fill="#007E77"/>
</g>
<defs>
<clipPath id="clip0_1564_106662">
<rect width="40" height="40" fill="white" transform="translate(8 8)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,11 @@
<svg width="56" height="56" viewBox="0 0 56 56" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="56" height="56" rx="28" fill="#E4A6C7"/>
<g clip-path="url(#clip0_1564_106675)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M27.21 10.2375L23.185 8.89505C22.8488 8.7833 22.4926 8.7443 22.1401 8.78064C21.7877 8.81698 21.447 8.92783 21.1406 9.10583C20.8342 9.28384 20.5692 9.52494 20.3631 9.81315C20.1569 10.1014 20.0144 10.4301 19.945 10.7775L18.5 18H14.25C13.9185 18 13.6005 18.1317 13.3661 18.3662C13.1317 18.6006 13 18.9185 13 19.25C13 19.5816 13.1317 19.8995 13.3661 20.1339C13.6005 20.3684 13.9185 20.5 14.25 20.5H18.315C17.8121 22.4489 17.908 24.504 18.59 26.3976L13.41 25.535C13.052 25.4755 12.6854 25.4947 12.3355 25.5911C11.9857 25.6876 11.661 25.859 11.3841 26.0936C11.1072 26.3282 10.8847 26.6202 10.732 26.9494C10.5793 27.2786 10.5002 27.6372 10.5 28V30.5C11.41 30.5 12.265 30.7425 13 31.17V28L15.5 28.4175L20.1475 29.1925L25.555 30.0925L26.75 30.2925V45.2925L13 43V39.83C12.2404 40.27 11.3779 40.5012 10.5 40.5V43C10.5003 43.5918 10.7105 44.1643 11.0931 44.6157C11.4758 45.067 12.0062 45.368 12.59 45.465L27.59 47.965C27.86 48.01 28.14 48.01 28.41 47.965L43.41 45.465C43.9938 45.368 44.5242 45.067 44.9068 44.6157C45.2895 44.1643 45.4997 43.5918 45.5 43V40.5C44.6222 40.5012 43.7596 40.27 43 39.83V43L29.25 45.2925V30.2925L30.445 30.0925L35.8525 29.1925L40.5 28.4151L43 28V31.17C43.7596 30.7301 44.6222 30.4989 45.5 30.5V28C45.4998 27.6372 45.4207 27.2786 45.268 26.9494C45.1153 26.6202 44.8928 26.3282 44.6159 26.0936C44.339 25.859 44.0143 25.6876 43.6645 25.5911C43.3146 25.4947 42.948 25.4755 42.59 25.535L37.4075 26.3976C38.0928 24.5047 38.1896 22.4489 37.685 20.5H41.75C42.0815 20.5 42.3995 20.3684 42.6339 20.1339C42.8683 19.8995 43 19.5816 43 19.25C43 18.9185 42.8683 18.6006 42.6339 18.3662C42.3995 18.1317 42.0815 18 41.75 18H37.5L36.055 10.775C35.985 10.4277 35.842 10.0993 35.6355 9.81142C35.4289 9.52357 35.1636 9.2829 34.857 9.10537C34.5504 8.92784 34.2095 8.81751 33.8571 8.78168C33.5046 8.74585 33.1486 8.78535 32.8125 8.89755L28.79 10.2375C28.2772 10.4084 27.7228 10.4084 27.21 10.2375ZM34.41 26.8976C34.9862 25.9464 35.3447 24.8795 35.4597 23.7733C35.5747 22.6672 35.4433 21.5494 35.075 20.5H20.925C20.5567 21.5494 20.4253 22.6672 20.5403 23.7733C20.6553 24.8795 21.0138 25.9464 21.59 26.8976L28 27.965L34.41 26.8976ZM35 18H31L30.5 15.5L34.25 14.25L35 18ZM10.5 38C11.163 38 11.7989 37.7367 12.2678 37.2678C12.7366 36.799 13 36.1631 13 35.5C13 34.837 12.7366 34.2011 12.2678 33.7323C11.7989 33.2634 11.163 33 10.5 33C9.83696 33 9.20107 33.2634 8.73223 33.7323C8.26339 34.2011 8 34.837 8 35.5C8 36.1631 8.26339 36.799 8.73223 37.2678C9.20107 37.7367 9.83696 38 10.5 38ZM45.5 38C46.163 38 46.7989 37.7367 47.2678 37.2678C47.7366 36.799 48 36.1631 48 35.5C48 34.837 47.7366 34.2011 47.2678 33.7323C46.7989 33.2634 46.163 33 45.5 33C44.837 33 44.2011 33.2634 43.7322 33.7323C43.2634 34.2011 43 34.837 43 35.5C43 36.1631 43.2634 36.799 43.7322 37.2678C44.2011 37.7367 44.837 38 45.5 38Z" fill="#C4407C"/>
</g>
<defs>
<clipPath id="clip0_1564_106675">
<rect width="40" height="40" fill="white" transform="translate(8 8)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

View file

@ -36,6 +36,7 @@ import type {
LanguageDefinitionSnippetArguments,
} from '@kbn/search-api-panels';
import { useLocation } from 'react-router-dom';
import { CloudDetailsPanel, PipelinePanel } from '@kbn/search-api-panels';
import { docLinks } from '../../../common/doc_links';
import { useKibanaServices } from '../hooks/use_kibana';
import { useAssetBasePath } from '../hooks/use_asset_base_path';
@ -52,8 +53,6 @@ import { ApiKeyPanel } from './api_key/api_key';
import { ConnectorsCallout } from './connectors_callout';
import { ConnectorIngestionPanel } from './connectors_ingestion';
import { PipelineButtonOverview } from './pipeline_button_overview';
import { PipelinePanel } from './pipeline_panel';
import { CloudDetailsPanel } from './overview/cloud_details';
export const ElasticsearchOverview = () => {
const [selectedLanguage, setSelectedLanguage] = useState<LanguageDefinition>(javaDefinition);
@ -311,7 +310,13 @@ export const ElasticsearchOverview = () => {
}}
/>
}
leftPanelContent={<PipelinePanel />}
leftPanelContent={
<PipelinePanel
clusterImage={`${assetBasePath}/cluster.svg`}
cutImage={`${assetBasePath}/cut.svg`}
reporterImage={`${assetBasePath}/reporter.svg`}
/>
}
links={[]}
title={i18n.translate('xpack.serverlessSearch.pipeline.title', {
defaultMessage: 'Transform and enrich your data',

View file

@ -1,127 +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, { useState } from 'react';
import {
EuiCheckableCard,
EuiCodeBlock,
EuiFlexGroup,
EuiFlexItem,
EuiPanel,
EuiSpacer,
EuiText,
EuiThemeProvider,
EuiTitle,
EuiBadge,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { FormattedMessage } from '@kbn/i18n-react';
import { OverviewPanel } from '@kbn/search-api-panels';
export interface CloudDetailsPanelProps {
cloudId?: string;
elasticsearchUrl?: string;
}
enum CloudDetail {
ElasticsearchEndpoint = 'es_url',
CloudId = 'cloud_id',
}
export const CloudDetailsPanel = ({ cloudId, elasticsearchUrl }: CloudDetailsPanelProps) => {
const [selectedDetail, setSelectedCloudDetail] = useState<CloudDetail>(
CloudDetail.ElasticsearchEndpoint
);
return (
<OverviewPanel
description={i18n.translate('xpack.serverlessSearch.cloudIdDetails.description', {
defaultMessage: 'Get ready to ingest and query your data by choosing a connection option:',
})}
leftPanelContent={
<EuiThemeProvider colorMode="dark">
<EuiPanel paddingSize="xs">
<EuiCodeBlock isCopyable fontSize="m" className="serverlessSearchCloudDetailsCopyPanel">
{selectedDetail === CloudDetail.CloudId && cloudId}
{selectedDetail === CloudDetail.ElasticsearchEndpoint && elasticsearchUrl}
</EuiCodeBlock>
</EuiPanel>
</EuiThemeProvider>
}
links={[]}
title={i18n.translate('xpack.serverlessSearch.cloudIdDetails.title', {
defaultMessage: 'Copy your connection details',
})}
>
<EuiSpacer size="l" />
<EuiCheckableCard
id={CloudDetail.ElasticsearchEndpoint}
name={CloudDetail.ElasticsearchEndpoint}
label={
<EuiFlexGroup alignItems="center">
<EuiFlexItem>
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="xpack.serverlessSearch.cloudIdDetails.elasticsearchEndpoint.title"
defaultMessage="Elasticsearch endpoint"
/>
</h5>
</EuiTitle>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<span>
<EuiBadge color="success">
<FormattedMessage
id="xpack.serverlessSearch.cloudIdDetails.elasticsearchEndpoint.recommendedBadge"
defaultMessage="Recommended"
/>
</EuiBadge>
</span>
</EuiFlexItem>
</EuiFlexGroup>
}
checked={selectedDetail === CloudDetail.ElasticsearchEndpoint}
onChange={() => setSelectedCloudDetail(CloudDetail.ElasticsearchEndpoint)}
>
<EuiText size="s">
<p>
<FormattedMessage
id="xpack.serverlessSearch.cloudIdDetails.elasticsearchEndpoint.description"
defaultMessage="The most common method for establishing an Elasticsearch connection."
/>
</p>
</EuiText>
</EuiCheckableCard>
<EuiSpacer />
<EuiCheckableCard
id={CloudDetail.CloudId}
name={CloudDetail.CloudId}
label={
<EuiTitle size="xxs">
<h5>
<FormattedMessage
id="xpack.serverlessSearch.cloudIdDetails.cloudId.title"
defaultMessage="Cloud ID"
/>
</h5>
</EuiTitle>
}
checked={selectedDetail === CloudDetail.CloudId}
onChange={() => setSelectedCloudDetail(CloudDetail.CloudId)}
>
<EuiText size="s">
<p>
<FormattedMessage
id="xpack.serverlessSearch.cloudIdDetails.cloudId.description"
defaultMessage="Specific client libraries and connectors can use this unique identifier specific to Elastic Cloud."
/>
</p>
</EuiText>
</EuiCheckableCard>
</OverviewPanel>
);
};

View file

@ -13,9 +13,7 @@ import { i18n } from '@kbn/i18n';
import { useKibanaServices } from '../hooks/use_kibana';
export const PipelineButtonOverview: React.FC = () => {
const {
application: { navigateToUrl },
} = useKibanaServices();
const { http } = useKibanaServices();
return (
<>
@ -23,7 +21,7 @@ export const PipelineButtonOverview: React.FC = () => {
<EuiButton
iconType="plusInCircle"
size="s"
onClick={() => navigateToUrl('/app/management/ingest/ingest_pipelines/create')}
href={http.basePath.prepend('/app/management/ingest/ingest_pipelines/create')}
data-test-subj="create-a-pipeline-button"
>
<EuiText size="s">

View file

@ -9,7 +9,7 @@
"public/**/*.ts",
"public/**/*.tsx",
"server/**/*.ts",
"../../../typings/**/*"
"../../../typings/**/*",
],
"exclude": [
"target/**/*"

View file

@ -14782,9 +14782,6 @@
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.info": "Avant de pouvoir commencer à publier des documents dans votre index Elasticsearch, vous devez créer au moins une clé dAPI.",
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.learnMore": "En savoir plus sur les clés dAPI",
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.title": "Générer une clé dAPI",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.desc": "Identificateur unique pour votre déploiement. ",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.description": "Il vous faut identifier votre déploiement.",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.elasticTitle": "Stockez votre ULR Elasticsearch",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeydesc": "Identifiant privé et unique pour l'authentification et l'autorisation.",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeytitle": "Générer une clé dAPI",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.description": "Il vous faut votre clé d'API privée pour connecter votre appareil en toute sécurité. Copiez-la dans un endroit sûr.",
@ -15317,22 +15314,6 @@
"xpack.enterpriseSearch.overview.elasticsearchCard.button": "Démarrer",
"xpack.enterpriseSearch.overview.elasticsearchCard.description": "Concevez et créez des applications de recherche performantes et pertinentes ou des implémentations de recherche à grande échelle directement dans Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchCard.heading": "Lancez-vous avec Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.cloudIdLabel": "Identifiant du cloud",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.copyCloudIdAriaLabel": "Copier l'Identifiant du cloud",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.heading": "Mon Déploiement",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.manageApiKeysLink": "Gérer les clés d'API",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.manageLink": "Gérer",
"xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchDescription": "Elastic construit et assure la maintenance des clients dans plusieurs langues populaires et notre communauté a contribué à beaucoup d'autres.",
"xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchTitle": "Se connecter à Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsLink": "En savoir plus sur les clients Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectAriaLabel": "Clients de langage",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectLabel": "Sélectionner un client",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchDescription": "Elasticsearch fournit les outils de bas niveau dont vous avez besoin pour créer une recherche rapide et pertinente pour votre site web ou votre application. Grâce à sa puissance et sa flexibilité, Elasticsearch peut gérer des cas d'utilisation de toutes sortes en lien avec la recherche.",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceDescription": "Vous êtes prêt à ajouter une expérience de recherche moderne et attrayante à votre application ou à votre site web ? Search UI, le cadre de recherche JavaScript d'Elastic permettant de créer des expériences de recherche de classe mondiale, a été conçu pour cette tâche.",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceTitle": "Construire une expérience de recherche avec Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIGitHubLink": "Search UI sur GitHub",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIMarketingLink": "En savoir plus sur Search UI",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchTitle": "Prise en main d'Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchResources.createIndex": "Créer un nouvel index",
"xpack.enterpriseSearch.overview.elasticsearchResources.elasticsearchClients": "Configurer un client de langage",
"xpack.enterpriseSearch.overview.elasticsearchResources.gettingStarted": "Prise en main d'Elasticsearch",
@ -15341,7 +15322,6 @@
"xpack.enterpriseSearch.overview.emptyState.buttonTitle": "Ajouter du contenu à Search",
"xpack.enterpriseSearch.overview.emptyState.footerLinkTitle": "En savoir plus",
"xpack.enterpriseSearch.overview.emptyState.heading": "Ajouter du contenu à Search",
"xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleElastic": "Copier votre ULR Elasticsearch",
"xpack.enterpriseSearch.overview.gettingStarted.configureClient.description": "Initialiser votre client avec votre clé d'API unique",
"xpack.enterpriseSearch.overview.gettingStarted.configureClient.title": "Configurer votre client",
"xpack.enterpriseSearch.overview.gettingStarted.ingestData.description": "Ajoutez des données à votre flux de données ou à votre index pour les rendre interrogeables",
@ -36899,8 +36879,6 @@
"xpack.serverlessSearch.app.elasticsearch.title": "Elasticsearch",
"xpack.serverlessSearch.back": "Retour",
"xpack.serverlessSearch.cancel": "Annuler",
"xpack.serverlessSearch.cloudIdDetails.description": "Il vous faut l'identifiant et l'URL du cloud pour identifier votre projet et vous y connecter.",
"xpack.serverlessSearch.cloudIdDetails.title": "Copiez vos informations de connexion",
"xpack.serverlessSearch.configureClient.basicConfigLabel": "Configuration de base",
"xpack.serverlessSearch.configureClient.description": "Initialiser votre client avec votre clé dAPI et votre identifiant de cloud uniques",
"xpack.serverlessSearch.configureClient.title": "Configurer votre client",

View file

@ -14795,9 +14795,6 @@
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.info": "ElasticsearchドキュメントをElasticsearchインデックスに送信する前に、少なくとも1つのAPIキーを作成する必要があります。",
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.learnMore": "APIキーの詳細",
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.title": "APIキーを生成",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.desc": "デプロイ固有の識別子。",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.description": "デプロイを特定するために必要です。",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.elasticTitle": "Elasticsearch URLを保存",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeydesc": "認証と認可のための非公開の一意の識別子。",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeytitle": "APIキーを生成",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.description": "プロジェクトに安全に接続するには、非公開のAPIキーが必要です。安全な場所にコピーしてください。",
@ -15330,22 +15327,6 @@
"xpack.enterpriseSearch.overview.elasticsearchCard.button": "使ってみる",
"xpack.enterpriseSearch.overview.elasticsearchCard.description": "Elasticsearchで直接、パフォーマンスと関連性が高い、検索対応アプリケーションまたは大規模検索実装を設計して構築",
"xpack.enterpriseSearch.overview.elasticsearchCard.heading": "Elasticsearchをはじめよう",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.cloudIdLabel": "クラウドID",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.copyCloudIdAriaLabel": "クラウドIDのコピー",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.heading": "マイデプロイ",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.manageApiKeysLink": "APIキーの管理",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.manageLink": "管理",
"xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchDescription": "Elasticは複数の一般的な言語でクライアントを構築および保守します。Elasticのコミュニティはさらに多くを提供しています。",
"xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchTitle": "Elasticsearchに接続",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsLink": "Elasticsearchクライアントの詳細",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectAriaLabel": "言語クライアント",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectLabel": "クライアントを選択",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchDescription": "Elasticsearchは、Webサイトやアプリケーションで高速かつ関連性の高い検索を構築するために必要な低水準ツールを提供しています。高性能と柔軟性を備えているため、Elasticsearchはすべての形とサイズの検索ユースケースを処理できます。",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceDescription": "興味をそそる最新の検索エクスペリエンスをアプリケーションやWebサイトに追加しませんか。世界クラスの検索エクスペリエンスを構築するためのElasticのJavaScript検索フレームワークであるSearch UIを活用できます。",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceTitle": "Elasticsearchで検索エクスペリエンスを構築",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIGitHubLink": "GitHubのSearch UI",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIMarketingLink": "Search UIの詳細を参照してください",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchTitle": "Elasticsearchを使い始める",
"xpack.enterpriseSearch.overview.elasticsearchResources.createIndex": "新しいインデックスを作成",
"xpack.enterpriseSearch.overview.elasticsearchResources.elasticsearchClients": "言語クライアントのセットアップ",
"xpack.enterpriseSearch.overview.elasticsearchResources.gettingStarted": "Elasticsearchを使い始める",
@ -15354,7 +15335,6 @@
"xpack.enterpriseSearch.overview.emptyState.buttonTitle": "Searchにコンテンツを追加",
"xpack.enterpriseSearch.overview.emptyState.footerLinkTitle": "詳細",
"xpack.enterpriseSearch.overview.emptyState.heading": "Searchにコンテンツを追加",
"xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleElastic": "Elasticsearch URLをコピー",
"xpack.enterpriseSearch.overview.gettingStarted.configureClient.description": "一意のAPIキーでクライアントを初期化",
"xpack.enterpriseSearch.overview.gettingStarted.configureClient.title": "クライアントを構成",
"xpack.enterpriseSearch.overview.gettingStarted.ingestData.description": "データストリームやインデックスにデータを追加して、データを検索可能にする",
@ -36898,8 +36878,6 @@
"xpack.serverlessSearch.app.elasticsearch.title": "Elasticsearch",
"xpack.serverlessSearch.back": "戻る",
"xpack.serverlessSearch.cancel": "キャンセル",
"xpack.serverlessSearch.cloudIdDetails.description": "プロジェクトを識別して、それに接続するには、クラウドIDとクラウドURLが必要です。",
"xpack.serverlessSearch.cloudIdDetails.title": "接続詳細情報をコピー",
"xpack.serverlessSearch.configureClient.basicConfigLabel": "基本構成",
"xpack.serverlessSearch.configureClient.description": "一意のAPIキーとCloud IDでクライアントを初期化",
"xpack.serverlessSearch.configureClient.title": "クライアントを構成",

View file

@ -14795,9 +14795,6 @@
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.info": "在开始将文档发布到 Elasticsearch 索引之前,您至少需要创建一个 API 密钥。",
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.learnMore": "进一步了解 API 密钥",
"xpack.enterpriseSearch.content.overview.generateApiKeyModal.title": "生成 API 密钥",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.desc": "您的部署的唯一标识符。",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.description": "需要此项来标识您的部署。",
"xpack.enterpriseSearch.content.overview.gettingStarted.cloudId.elasticTitle": "存储您的 Elasticsearch URL",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeydesc": "用于身份验证和授权的专用唯一标识符。",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.apiKeytitle": "生成 API 密钥",
"xpack.enterpriseSearch.content.overview.gettingStarted.generateApiKeyPanel.description": "您需要私有 API 密钥以便安全连接到您的项目。将其复制到某个安全位置。",
@ -15330,22 +15327,6 @@
"xpack.enterpriseSearch.overview.elasticsearchCard.button": "开始使用",
"xpack.enterpriseSearch.overview.elasticsearchCard.description": "直接在 Elasticsearch 中设计并构建由相关搜索提供支持的高性能应用程序或大规模搜索实现",
"xpack.enterpriseSearch.overview.elasticsearchCard.heading": "Elasticsearch 入门",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.cloudIdLabel": "云 ID",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.copyCloudIdAriaLabel": "复制云 ID",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.heading": "我的部署",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.manageApiKeysLink": "管理 API 密钥",
"xpack.enterpriseSearch.overview.elasticsearchCloudId.manageLink": "管理",
"xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchDescription": "Elastic 以几种流行语言构建和维护客户端,我们的社区也做出了许多贡献。",
"xpack.enterpriseSearch.overview.elasticsearchGuide.connectToElasticsearchTitle": "连接到 Elasticsearch",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsLink": "详细了解 Elasticsearch 客户端",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectAriaLabel": "语言客户端",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchClientsSelectLabel": "选择客户端",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchDescription": "Elasticsearch 提供了为您的网站或应用程序构建快速的相关搜索所需的低级工具。由于功能强大而灵活Elasticsearch 可处理所有形状和规模的搜索用例。",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceDescription": "准备为您的应用程序或网站添加富于吸引力的现代搜索体验?搜索 UI 是 Elastic 用于构建世界级搜索体验的 JavaScript 搜索框架,它专为执行该任务而设计。",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchExperienceTitle": "使用 Elasticsearch 构建搜索体验",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIGitHubLink": "GitHub 上的搜索 UI",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchSearchUIMarketingLink": "详细了解搜索 UI",
"xpack.enterpriseSearch.overview.elasticsearchGuide.elasticsearchTitle": "Elasticsearch 入门",
"xpack.enterpriseSearch.overview.elasticsearchResources.createIndex": "创建新索引",
"xpack.enterpriseSearch.overview.elasticsearchResources.elasticsearchClients": "设置语言客户端",
"xpack.enterpriseSearch.overview.elasticsearchResources.gettingStarted": "Elasticsearch 入门",
@ -15354,7 +15335,6 @@
"xpack.enterpriseSearch.overview.emptyState.buttonTitle": "添加内容到 Search",
"xpack.enterpriseSearch.overview.emptyState.footerLinkTitle": "了解详情",
"xpack.enterpriseSearch.overview.emptyState.heading": "添加内容到 Search",
"xpack.enterpriseSearch.overview.gettingStarted.cloudId.panelTitleElastic": "复制您的 Elasticsearch URL",
"xpack.enterpriseSearch.overview.gettingStarted.configureClient.description": "使用唯一 API 密钥对客户端进行初始化",
"xpack.enterpriseSearch.overview.gettingStarted.configureClient.title": "配置客户端",
"xpack.enterpriseSearch.overview.gettingStarted.ingestData.description": "将数据添加到数据流或索引,使其可进行搜索",
@ -36893,8 +36873,6 @@
"xpack.serverlessSearch.app.elasticsearch.title": "Elasticsearch",
"xpack.serverlessSearch.back": "返回",
"xpack.serverlessSearch.cancel": "取消",
"xpack.serverlessSearch.cloudIdDetails.description": "您需要云 ID 和云 URL 以标识并连接到您的项目。",
"xpack.serverlessSearch.cloudIdDetails.title": "复制连接详情",
"xpack.serverlessSearch.configureClient.basicConfigLabel": "基本配置",
"xpack.serverlessSearch.configureClient.description": "使用唯一 API 密钥和云 ID 对客户端进行初始化",
"xpack.serverlessSearch.configureClient.title": "配置客户端",