Skip to content

Commit

Permalink
feat: upgrade to searchkit v4
Browse files Browse the repository at this point in the history
  • Loading branch information
Hironori Yamamoto committed Mar 9, 2023
1 parent 22ee4db commit 5f408e0
Show file tree
Hide file tree
Showing 12 changed files with 418 additions and 156 deletions.
3 changes: 2 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
LOG_LEVEL=INFO
REDASH__URL=
REDASH__API_KEY=
NEXT_PUBLIC_APP__URL=http://localhost:3000
NEXT_PUBLIC_REDASH__URL=${REDASH__URL}
OPEN_SEARCH__URL=http://opensearch-node-main:9200
OPEN_SEARCH__URL=http://localhost:9200
OPEN_SEARCH__USERNAME=admin
OPEN_SEARCH__PASSWORD=admin
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,39 @@ import {
Stats,
InfiniteHits,
InstantSearchProps,
Hits,
} from "react-instantsearch-dom";
import Hit from "./Hit";
import Hit from "../components/Hit";

export function App(props: InstantSearchProps) {
interface CurrentRefinementItem {
id: string;
index: string;
attribute: string;
label: string;
currentRefinement: string[];
}

const reduceDuplicateRefinement = (items: CurrentRefinementItem[]) => {
const seen = new Set();
return items.filter((item: any) => {
if (seen.has(item.label)) {
return false;
} else {
seen.add(item.label);
return true;
}
});
};

export default function App(props: InstantSearchProps) {
return (
<div className="ais-InstantSearch">
<InstantSearch {...props}>
<EuiPageTemplate panelled={true}>
<EuiPageTemplate.Header>
<EuiPageTemplate.Sidebar>
<EuiTitle size="l">
<h1>Redash Search</h1>
<h1>Redash Searcher</h1>
</EuiTitle>
</EuiPageTemplate.Header>
<EuiPageTemplate.Sidebar>
<EuiTitle size="xs">
<h4>Data Source</h4>
</EuiTitle>
Expand Down Expand Up @@ -54,6 +73,9 @@ export function App(props: InstantSearchProps) {
<EuiPageTemplate.Section>
<SearchBox />
<Stats />
<div style={{ margin: "1rem 0" }}>
<CurrentRefinements transformItems={reduceDuplicateRefinement} />
</div>
</EuiPageTemplate.Section>
<EuiPageTemplate.Section>
<InfiniteHits hitComponent={Hit} />
Expand Down
49 changes: 33 additions & 16 deletions redash-searcher-web/components/HighlightedQuery.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,39 @@
import { EuiCallOut, EuiText } from "@elastic/eui";
import dompurify from "dompurify";
import { EuiCallOut } from "@elastic/eui";
import { connectHighlight } from "react-instantsearch-dom";

export interface HighlightedQueryProps {
query: string;
}
const deliminator = "|||";
const re = RegExp(`$\|\|\|(.*)${deliminator}\|\|\|`, "g");

export const HighlightedQuery: React.FC<HighlightedQueryProps> = ({
query,
}: HighlightedQueryProps) => {
const sanitizer = dompurify.sanitize;
const HighlightQueryInner = ({ highlight, attribute, hit }: any) => {
const parsedHit = highlight({
highlightProperty: "_highlightResult",
attribute,
hit,
});
return (
<EuiCallOut>
<p
style={{ whiteSpace: "pre-wrap" }}
dangerouslySetInnerHTML={{
__html: sanitizer(query),
}}
/>
<EuiCallOut
style={{ whiteSpace: "pre-wrap", maxWidth: "1000px" }}
color={"success"}
>
<span className="ais-Highlight">
<span>
{parsedHit.map((part: any, index: number) =>
part.isHighlighted ? (
<mark className="ais-Highlight-highlighted" key={index}>
{part.value}
</mark>
) : (
<span className="ais-Highlight-nonHighlighted" key={index}>
{part.value}
</span>
)
)}
</span>
</span>
</EuiCallOut>
);
};

const HighlightedQuery = connectHighlight(HighlightQueryInner);

export default HighlightedQuery;
140 changes: 69 additions & 71 deletions redash-searcher-web/components/Hit.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import {
EuiFlexGroup,
EuiAvatar,
} from "@elastic/eui";
import HighlightedQuery from "./HighlightedQuery";

export interface HitProps {
hit: HitCore<IResultHitField>
hit: HitCore<IResultHitField>;
}

const REDASH_URL = (process.env.NEXT_PUBLIC_REDASH__URL || "").replace(
Expand All @@ -20,75 +21,72 @@ const REDASH_URL = (process.env.NEXT_PUBLIC_REDASH__URL || "").replace(
);

const Hit: React.FC<HitProps> = ({ hit }: HitProps) => {
return (
<EuiCard
layout="horizontal"
icon={
<EuiAvatar
name={`logo-${hit.data_source_type}`}
size="l"
imageUrl={`${REDASH_URL}/static/images/db-logos/${hit.data_source_type}.png`}
color="#e0e5ee"
/>
}
title={hit.name}
href={`${REDASH_URL}/queries/${hit.id}/source`}
description={hit.description}
>
<EuiFlexGrid gutterSize="xl">
<EuiFlexGroup>
<EuiFlexItem grow={5}>
<EuiDescriptionList
textStyle="reverse"
listItems={[
{
title: "Data Source Type",
description: hit.data_source_type,
},
{
title: "Author",
description: hit.user_name,
},
{
title: "Tags",
description: hit.tags.join(", ") || "No Tags",
},
]}
/>
</EuiFlexItem>
<EuiFlexItem grow={5}>
<EuiDescriptionList
textStyle="reverse"
listItems={[
{
title: "Data Source Name",
description: hit.data_source_name,
},
{
title: "Created At",
description: hit.created_at,
},
{
title: "Updated At",
description: hit.updated_at,
},
]}
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFlexGrid>
{/* {hit.highlight.query && (
<>
<EuiSpacer />
<HighlightedQuery
query={hit.highlight.query
.reduce((acc, cur) => acc + "\n...\n" + cur)
.replaceAll("\n", "<br/>")}
/>
</>
)} */}
</EuiCard>
)
}
return (
<EuiCard
layout="horizontal"
icon={
<EuiAvatar
name={`logo-${hit.data_source_type}`}
size="l"
imageUrl={`${REDASH_URL}/static/images/db-logos/${hit.data_source_type}.png`}
color="#e0e5ee"
/>
}
title={hit.name}
href={`${REDASH_URL}/queries/${hit.id}/source`}
description={hit.description}
>
<EuiFlexGrid gutterSize="xl">
<EuiFlexGroup>
<EuiFlexItem grow={5}>
<EuiDescriptionList
textStyle="reverse"
listItems={[
{
title: "Data Source Type",
description: hit.data_source_type,
},
{
title: "Author",
description: hit.user_name,
},
{
title: "Tags",
description: hit.tags.join(", ") || "No Tags",
},
]}
/>
</EuiFlexItem>
<EuiFlexItem grow={5}>
<EuiDescriptionList
textStyle="reverse"
listItems={[
{
title: "Data Source Name",
description: hit.data_source_name,
},
{
title: "Created At",
description: hit.created_at,
},
{
title: "Updated At",
description: hit.updated_at,
},
]}
/>
</EuiFlexItem>
</EuiFlexGroup>
{hit._highlightResult.query?.matchedWords.length !== 0 && (
<EuiFlexGroup>
<EuiFlexItem grow={5}>
<HighlightedQuery hit={hit} attribute="query"></HighlightedQuery>
</EuiFlexItem>
</EuiFlexGroup>
)}
</EuiFlexGrid>
</EuiCard>
);
};

export default Hit;
1 change: 1 addition & 0 deletions redash-searcher-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"next-with-apollo": "5.1.0",
"qs": "^6.11.0",
"react": "18.2.0",
"react-code-blocks": "^0.0.9-0",
"react-dom": "18.2.0",
"react-instantsearch-dom": "^6.39.0",
"react-syntax-highlighter": "^15.5.0",
Expand Down
6 changes: 6 additions & 0 deletions redash-searcher-web/pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import "instantsearch.css/themes/satellite-min.css";
import "../styles.css";

export default function App({ Component, pageProps }: any): JSX.Element {
return <Component {...pageProps} />;
}
6 changes: 0 additions & 6 deletions redash-searcher-web/pages/api/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,3 @@ export interface IResultHitHighlight {
name: string[];
query: string[];
}

export interface IResultHitItem {
id: string;
fields: IResultHitField;
highlight: IResultHitHighlight;
}
2 changes: 1 addition & 1 deletion redash-searcher-web/pages/api/search.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ const getOpenSearchConnection = (): ConfigConnection => {
const client = Client({
connection: getOpenSearchConnection(),
search_settings: {
highlight_attributes: ["name"],
highlight_attributes: ["name", "query"],
search_attributes: ["name", "query"],
result_attributes: [
"id",
Expand Down
Loading

0 comments on commit 5f408e0

Please sign in to comment.