Skip to content

Commit a2f68c6

Browse files
reakaleekMpdreamz
andauthored
Add ElasticsearchGateway and UI adjustments (#1708)
* Add ElasticsearchGateway and UI adjustments * Fix lint * Fix eslint errors and run prettier * Use new GetMappingSettings * Refactor and fix duplicate breadcrumbs * bump Elasticsearch version and Elastic.Ingest * Include typo fix from elastic ingest * Update to latest elasticsearch client * Apply suggestions from code review Remove Console.WriteLines --------- Co-authored-by: Martijn Laarman <[email protected]>
1 parent 59f51e8 commit a2f68c6

File tree

18 files changed

+647
-137
lines changed

18 files changed

+647
-137
lines changed

Directory.Packages.props

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@
2323
<PackageVersion Include="AWSSDK.SQS" Version="4.0.0.1" />
2424
<PackageVersion Include="AWSSDK.S3" Version="4.0.0.1" />
2525
<PackageVersion Include="Elastic.Aspire.Hosting.Elasticsearch" Version="9.3.0" />
26+
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="9.1.4" />
2627
<PackageVersion Include="FakeItEasy" Version="8.3.0" />
27-
<PackageVersion Include="Elastic.Ingest.Elasticsearch" Version="0.11.3" />
28+
<PackageVersion Include="Elastic.Ingest.Elasticsearch" Version="0.14.0" />
2829
<PackageVersion Include="InMemoryLogger" Version="1.0.66" />
2930
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.6.0" />
3031
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />

src/Elastic.Documentation.Site/Assets/web-components/SearchOrAskAi/AskAi/AskAiSuggestions.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
import { useSearchActions, useSearchTerm } from '../search.store'
2-
import { EuiButton, EuiSpacer, EuiText, useEuiTheme } from '@elastic/eui'
2+
import {
3+
EuiButton,
4+
EuiIcon,
5+
EuiSpacer,
6+
EuiText,
7+
useEuiTheme,
8+
} from '@elastic/eui'
39
import { css } from '@emotion/react'
410
import * as React from 'react'
511

@@ -26,7 +32,16 @@ export const AskAiSuggestions = (props: Props) => {
2632
`
2733
return (
2834
<>
29-
<EuiText size="xs">Ask Elastic Docs AI Assistant</EuiText>
35+
<div
36+
css={css`
37+
display: flex;
38+
gap: ${euiTheme.size.s};
39+
align-items: center;
40+
`}
41+
>
42+
<EuiIcon type="sparkles" color="subdued" size="s" />
43+
<EuiText size="xs">Ask Elastic Docs AI Assistant</EuiText>
44+
</div>
3045
<EuiSpacer size="s" />
3146
{searchTerm && (
3247
<EuiButton
Lines changed: 190 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,32 @@
11
import { useSearchTerm } from '../search.store'
2-
import { useSearchQuery } from './useSearchQuery'
2+
import { SearchResultItem, useSearchQuery } from './useSearchQuery'
33
import {
4-
EuiButton,
4+
useEuiFontSize,
5+
EuiHighlight,
6+
EuiLink,
57
EuiLoadingSpinner,
68
EuiSpacer,
79
EuiText,
810
useEuiTheme,
11+
EuiIcon,
12+
EuiPagination,
913
} from '@elastic/eui'
1014
import { css } from '@emotion/react'
15+
import { useDebounce } from '@uidotdev/usehooks'
1116
import * as React from 'react'
17+
import { useEffect, useMemo, useState } from 'react'
1218

1319
export const SearchResults = () => {
1420
const searchTerm = useSearchTerm()
15-
const { data, error, isLoading } = useSearchQuery()
21+
const [activePage, setActivePage] = useState(0)
22+
const debouncedSearchTerm = useDebounce(searchTerm, 300)
23+
useEffect(() => {
24+
setActivePage(0)
25+
}, [debouncedSearchTerm])
26+
const { data, error, isLoading, isFetching } = useSearchQuery({
27+
searchTerm,
28+
pageNumber: activePage + 1,
29+
})
1630
const { euiTheme } = useEuiTheme()
1731

1832
if (!searchTerm) {
@@ -23,88 +37,193 @@ export const SearchResults = () => {
2337
return <div>Error loading search results: {error.message}</div>
2438
}
2539

26-
if (isLoading) {
27-
return (
28-
<div>
29-
<EuiLoadingSpinner size="s" /> Loading search results...
40+
return (
41+
<div>
42+
<div
43+
css={css`
44+
display: flex;
45+
gap: ${euiTheme.size.s};
46+
align-items: center;
47+
`}
48+
>
49+
{isLoading || isFetching ? (
50+
<EuiLoadingSpinner size="s" />
51+
) : (
52+
<EuiIcon type="search" color="subdued" size="s" />
53+
)}
54+
<EuiText size="xs">
55+
Search results for{' '}
56+
<span
57+
css={css`
58+
font-weight: ${euiTheme.font.weight.bold};
59+
`}
60+
>
61+
{searchTerm}
62+
</span>
63+
</EuiText>
3064
</div>
31-
)
32-
}
65+
<EuiSpacer size="s" />
66+
{data && (
67+
<>
68+
<ul>
69+
{data.results.map((result) => (
70+
<SearchResultListItem item={result} />
71+
))}
72+
</ul>
73+
<div
74+
css={css`
75+
display: flex;
76+
justify-content: flex-end;
77+
`}
78+
>
79+
<EuiPagination
80+
aria-label="Many pages example"
81+
pageCount={Math.min(data.pageCount, 10)}
82+
activePage={activePage}
83+
onPageClick={(activePage) =>
84+
setActivePage(activePage)
85+
}
86+
/>
87+
</div>
88+
</>
89+
)}
90+
</div>
91+
)
92+
}
3393

34-
if (!data || data.results.length === 0) {
35-
return <EuiText size="xs">No results found for "{searchTerm}"</EuiText>
36-
}
94+
interface SearchResultListItemProps {
95+
item: SearchResultItem
96+
}
97+
98+
function SearchResultListItem({ item: result }: SearchResultListItemProps) {
99+
const { euiTheme } = useEuiTheme()
100+
const searchTerm = useSearchTerm()
101+
const highlightSearchTerms = useMemo(
102+
() => searchTerm.toLowerCase().split(' '),
103+
[searchTerm]
104+
)
37105

38-
const buttonCss = css`
39-
border: none;
40-
vertical-align: top;
41-
justify-content: flex-start;
42-
block-size: 100%;
43-
padding-block: 4px;
44-
& > span {
45-
justify-content: flex-start;
46-
align-items: flex-start;
47-
}
48-
svg {
49-
color: ${euiTheme.colors.textSubdued};
50-
}
51-
.euiIcon {
52-
margin-top: 4px;
53-
}
54-
`
106+
if (highlightSearchTerms.includes('esql')) {
107+
highlightSearchTerms.push('es|ql')
108+
}
55109

56-
const trimDescription = (description: string) => {
57-
const limit = 200
58-
return description.length > limit
59-
? description.slice(0, limit) + '...'
60-
: description
110+
if (highlightSearchTerms.includes('dotnet')) {
111+
highlightSearchTerms.push('.net')
61112
}
113+
return (
114+
<li key={result.url}>
115+
<div
116+
tabIndex={0}
117+
css={css`
118+
display: flex;
119+
align-items: flex-start;
120+
gap: ${euiTheme.size.s};
121+
padding-inline: ${euiTheme.size.s};
122+
padding-block: ${euiTheme.size.xs};
123+
border-radius: ${euiTheme.border.radius.small};
124+
:hover {
125+
background-color: ${euiTheme.colors.backgroundTransparentSubdued};
126+
`}
127+
>
128+
<EuiIcon
129+
type="document"
130+
color="subdued"
131+
css={css`
132+
margin-top: ${euiTheme.size.xs};
133+
`}
134+
/>
135+
<div
136+
css={css`
137+
width: 100%;
138+
text-align: left;
139+
`}
140+
>
141+
<EuiLink
142+
tabIndex={-1}
143+
href={result.url}
144+
css={css`
145+
.euiMark {
146+
background-color: ${euiTheme.colors
147+
.backgroundLightWarning};
148+
font-weight: inherit;
149+
}
150+
`}
151+
>
152+
<EuiHighlight
153+
search={highlightSearchTerms}
154+
highlightAll={true}
155+
>
156+
{result.title}
157+
</EuiHighlight>
158+
</EuiLink>
159+
<Breadcrumbs
160+
parents={result.parents}
161+
highlightSearchTerms={highlightSearchTerms}
162+
/>
163+
</div>
164+
</div>
165+
</li>
166+
)
167+
}
62168

169+
function Breadcrumbs({
170+
parents,
171+
highlightSearchTerms,
172+
}: {
173+
parents: SearchResultItem['parents']
174+
highlightSearchTerms: string[]
175+
}) {
176+
const { euiTheme } = useEuiTheme()
177+
const { fontSize: smallFontsize } = useEuiFontSize('xs')
63178
return (
64-
<div
65-
css={`
66-
li:not(:first-child) {
67-
margin-top: ${euiTheme.size.xs};
68-
}
179+
<ul
180+
css={css`
181+
margin-top: 2px;
182+
display: flex;
183+
gap: 0 ${euiTheme.size.xs};
184+
flex-wrap: wrap;
185+
list-style: none;
69186
`}
70187
>
71-
<EuiText size="xs">Search Results for "{searchTerm}"</EuiText>
72-
<EuiSpacer size="s" />
73-
<ul>
74-
{data.results.map((result) => (
75-
<li key={result.url}>
76-
<EuiButton
77-
css={buttonCss}
78-
iconType="document"
79-
color="text"
80-
size="s"
81-
fullWidth
82-
>
83-
<div
188+
{parents
189+
.slice(1) // skip /docs
190+
.map((parent) => (
191+
<li
192+
key={'breadcrumb-' + parent.url}
193+
css={css`
194+
&:not(:last-child)::after {
195+
content: '/';
196+
margin-left: ${euiTheme.size.xs};
197+
font-size: ${smallFontsize};
198+
color: ${euiTheme.colors.text};
199+
margin-top: -1px;
200+
}
201+
display: inline-flex;
202+
`}
203+
>
204+
<EuiLink href={parent.url} color="text" tabIndex={-1}>
205+
<EuiText
206+
size="xs"
207+
color="subdued"
84208
css={css`
85-
width: 100%;
86-
text-align: left;
209+
.euiMark {
210+
background-color: transparent;
211+
text-decoration: underline;
212+
color: inherit;
213+
font-weight: inherit;
214+
}
87215
`}
88216
>
89-
{result.title}
90-
<EuiSpacer size="xs" />
91-
<EuiText
92-
css={css`
93-
text-wrap: pretty;
94-
`}
95-
textAlign="left"
96-
size="xs"
97-
color="subdued"
217+
<EuiHighlight
218+
search={highlightSearchTerms}
219+
highlightAll={true}
98220
>
99-
{trimDescription(result.description)}
100-
</EuiText>
101-
</div>
102-
</EuiButton>
103-
{/*<EuiIcon type="document" color="subdued" />*/}
104-
{/*<EuiText>{result.title}</EuiText>*/}
221+
{parent.title}
222+
</EuiHighlight>
223+
</EuiText>
224+
</EuiLink>
105225
</li>
106226
))}
107-
</ul>
108-
</div>
227+
</ul>
109228
)
110229
}

0 commit comments

Comments
 (0)