Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,8 @@
<PackageVersion Include="AWSSDK.SQS" Version="4.0.0.1" />
<PackageVersion Include="AWSSDK.S3" Version="4.0.0.1" />
<PackageVersion Include="Elastic.Aspire.Hosting.Elasticsearch" Version="9.3.0" />
<PackageVersion Include="Elastic.Clients.Elasticsearch" Version="9.1.4" />
<PackageVersion Include="FakeItEasy" Version="8.3.0" />
<PackageVersion Include="Elastic.Ingest.Elasticsearch" Version="0.14.0" />
<PackageVersion Include="Elastic.Ingest.Elasticsearch" Version="0.11.3" />
<PackageVersion Include="InMemoryLogger" Version="1.0.66" />
<PackageVersion Include="MartinCostello.Logging.XUnit.v3" Version="0.6.0" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.4" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,5 @@
import { useSearchActions, useSearchTerm } from '../search.store'
import {
EuiButton,
EuiIcon,
EuiSpacer,
EuiText,
useEuiTheme,
} from '@elastic/eui'
import { EuiButton, EuiSpacer, EuiText, useEuiTheme } from '@elastic/eui'
import { css } from '@emotion/react'
import * as React from 'react'

Expand All @@ -32,16 +26,7 @@ export const AskAiSuggestions = (props: Props) => {
`
return (
<>
<div
css={css`
display: flex;
gap: ${euiTheme.size.s};
align-items: center;
`}
>
<EuiIcon type="sparkles" color="subdued" size="s" />
<EuiText size="xs">Ask Elastic Docs AI Assistant</EuiText>
</div>
<EuiText size="xs">Ask Elastic Docs AI Assistant</EuiText>
<EuiSpacer size="s" />
{searchTerm && (
<EuiButton
Expand Down
Original file line number Diff line number Diff line change
@@ -1,32 +1,18 @@
import { useSearchTerm } from '../search.store'
import { SearchResultItem, useSearchQuery } from './useSearchQuery'
import { useSearchQuery } from './useSearchQuery'
import {
useEuiFontSize,
EuiHighlight,
EuiLink,
EuiButton,
EuiLoadingSpinner,
EuiSpacer,
EuiText,
useEuiTheme,
EuiIcon,
EuiPagination,
} from '@elastic/eui'
import { css } from '@emotion/react'
import { useDebounce } from '@uidotdev/usehooks'
import * as React from 'react'
import { useEffect, useMemo, useState } from 'react'

export const SearchResults = () => {
const searchTerm = useSearchTerm()
const [activePage, setActivePage] = useState(0)
const debouncedSearchTerm = useDebounce(searchTerm, 300)
useEffect(() => {
setActivePage(0)
}, [debouncedSearchTerm])
const { data, error, isLoading, isFetching } = useSearchQuery({
searchTerm,
pageNumber: activePage + 1,
})
const { data, error, isLoading } = useSearchQuery()
const { euiTheme } = useEuiTheme()

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

return (
<div>
<div
css={css`
display: flex;
gap: ${euiTheme.size.s};
align-items: center;
`}
>
{isLoading || isFetching ? (
<EuiLoadingSpinner size="s" />
) : (
<EuiIcon type="search" color="subdued" size="s" />
)}
<EuiText size="xs">
Search results for{' '}
<span
css={css`
font-weight: ${euiTheme.font.weight.bold};
`}
>
{searchTerm}
</span>
</EuiText>
if (isLoading) {
return (
<div>
<EuiLoadingSpinner size="s" /> Loading search results...
</div>
<EuiSpacer size="s" />
{data && (
<>
<ul>
{data.results.map((result) => (
<SearchResultListItem item={result} />
))}
</ul>
<div
css={css`
display: flex;
justify-content: flex-end;
`}
>
<EuiPagination
aria-label="Many pages example"
pageCount={Math.min(data.pageCount, 10)}
activePage={activePage}
onPageClick={(activePage) =>
setActivePage(activePage)
}
/>
</div>
</>
)}
</div>
)
}

interface SearchResultListItemProps {
item: SearchResultItem
}

function SearchResultListItem({ item: result }: SearchResultListItemProps) {
const { euiTheme } = useEuiTheme()
const searchTerm = useSearchTerm()
const highlightSearchTerms = useMemo(
() => searchTerm.toLowerCase().split(' '),
[searchTerm]
)
)
}

if (highlightSearchTerms.includes('esql')) {
highlightSearchTerms.push('es|ql')
if (!data || data.results.length === 0) {
return <EuiText size="xs">No results found for "{searchTerm}"</EuiText>
}

if (highlightSearchTerms.includes('dotnet')) {
highlightSearchTerms.push('.net')
const buttonCss = css`
border: none;
vertical-align: top;
justify-content: flex-start;
block-size: 100%;
padding-block: 4px;
& > span {
justify-content: flex-start;
align-items: flex-start;
}
svg {
color: ${euiTheme.colors.textSubdued};
}
.euiIcon {
margin-top: 4px;
}
`

const trimDescription = (description: string) => {
const limit = 200
return description.length > limit
? description.slice(0, limit) + '...'
: description
}
return (
<li key={result.url}>
<div
tabIndex={0}
css={css`
display: flex;
align-items: flex-start;
gap: ${euiTheme.size.s};
padding-inline: ${euiTheme.size.s};
padding-block: ${euiTheme.size.xs};
border-radius: ${euiTheme.border.radius.small};
:hover {
background-color: ${euiTheme.colors.backgroundTransparentSubdued};
`}
>
<EuiIcon
type="document"
color="subdued"
css={css`
margin-top: ${euiTheme.size.xs};
`}
/>
<div
css={css`
width: 100%;
text-align: left;
`}
>
<EuiLink
tabIndex={-1}
href={result.url}
css={css`
.euiMark {
background-color: ${euiTheme.colors
.backgroundLightWarning};
font-weight: inherit;
}
`}
>
<EuiHighlight
search={highlightSearchTerms}
highlightAll={true}
>
{result.title}
</EuiHighlight>
</EuiLink>
<Breadcrumbs
parents={result.parents}
highlightSearchTerms={highlightSearchTerms}
/>
</div>
</div>
</li>
)
}

function Breadcrumbs({
parents,
highlightSearchTerms,
}: {
parents: SearchResultItem['parents']
highlightSearchTerms: string[]
}) {
const { euiTheme } = useEuiTheme()
const { fontSize: smallFontsize } = useEuiFontSize('xs')
return (
<ul
css={css`
margin-top: 2px;
display: flex;
gap: 0 ${euiTheme.size.xs};
flex-wrap: wrap;
list-style: none;
<div
css={`
li:not(:first-child) {
margin-top: ${euiTheme.size.xs};
}
`}
>
{parents
.slice(1) // skip /docs
.map((parent) => (
<li
key={'breadcrumb-' + parent.url}
css={css`
&:not(:last-child)::after {
content: '/';
margin-left: ${euiTheme.size.xs};
font-size: ${smallFontsize};
color: ${euiTheme.colors.text};
margin-top: -1px;
}
display: inline-flex;
`}
>
<EuiLink href={parent.url} color="text" tabIndex={-1}>
<EuiText
size="xs"
color="subdued"
<EuiText size="xs">Search Results for "{searchTerm}"</EuiText>
<EuiSpacer size="s" />
<ul>
{data.results.map((result) => (
<li key={result.url}>
<EuiButton
css={buttonCss}
iconType="document"
color="text"
size="s"
fullWidth
>
<div
css={css`
.euiMark {
background-color: transparent;
text-decoration: underline;
color: inherit;
font-weight: inherit;
}
width: 100%;
text-align: left;
`}
>
<EuiHighlight
search={highlightSearchTerms}
highlightAll={true}
{result.title}
<EuiSpacer size="xs" />
<EuiText
css={css`
text-wrap: pretty;
`}
textAlign="left"
size="xs"
color="subdued"
>
{parent.title}
</EuiHighlight>
</EuiText>
</EuiLink>
{trimDescription(result.description)}
</EuiText>
</div>
</EuiButton>
{/*<EuiIcon type="document" color="subdued" />*/}
{/*<EuiText>{result.title}</EuiText>*/}
</li>
))}
</ul>
</ul>
</div>
)
}
Loading
Loading