Skip to content

Commit

Permalink
Add summarization. (#65)
Browse files Browse the repository at this point in the history
* Refactor web-component prop-passing to support function props.
* Use serializedprops name to clarify intention.
* Rename isDeeplinkable prop to isDeepLinkable.
* fetchSearchResults now resolves to { searchResults: DeserializedSearchResult[]; summary?: string }.
  • Loading branch information
cjcenizal authored May 7, 2024
1 parent d6bac29 commit fec3fa9
Show file tree
Hide file tree
Showing 29 changed files with 585 additions and 235 deletions.
22 changes: 17 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ import { ReactSearch } from "@vectara/react-search";
corpusId="CORPUS_ID"
apiKey="API_KEY"
placeholder="Placeholder" // Optional search input placeholder
isDeeplinkable={true} // Optional boolean determining if search results will be deeplinked
isDeepLinkable={true} // Optional boolean determining if search results will be deep-linked
openResultsInNewTab={true} // Optional boolean determining if links will open in a new tab
zIndex={/* Optional number assigned to the z-index of the search modal */}
/>
Expand Down Expand Up @@ -83,7 +83,7 @@ By default, React-Search sends query requests to the Vectara servers. If you wan

Configure the placeholder text in the search modal's input.

##### `isDeeplinkable` (optional)
##### `isDeepLinkable` (optional)

Defaults to `false`. Set this option if you want to persist a search query to a URL parameter. This will enable users to share or bookmark the URL. Loading the URL will automatically open the search modal and search for the query that's stored in the URL.

Expand All @@ -93,7 +93,19 @@ Defaults to `false`. Set this option if you want a search result to open in a ne

##### `zIndex` (optional)

Customize the z-index of the search modal
Define the z-index of the search modal.

##### `onToggleSummary` (optional)

Accepts a callback that will receive a boolean argument indicating whether the "Summarize search results" toggle is enabled.

##### `isSummaryToggleVisible` (optional)

Whether users will be able to summarize search results or not.

##### `isSummaryToggleInitiallyEnabled` (optional)

If users can toggle summarization, whether the toggle should be enabled by defualt.

### Power your own search UI with the useSearch hook

Expand All @@ -117,9 +129,9 @@ The values returned by the hook can be passed on to your custom components as pr

#### <u>Hook Values</u>

##### fetchSearchResults: `async (query: string) => Promise<DeserializedSearchResult[]>`
##### fetchSearchResults: `async (query: string, summarize: boolean) => Promise<{ searchResults: DeserializedSearchResult[]; summary?: string }>`

This is used to send a message to the search API. When the search succeeds, an array of search results is returned. Each search result is a `DeserializedSearchResult` object. More information on types can be found [here](src/types.ts).
This is used to send a message to the search API. When the search succeeds, an object consisting of an array of search results and an optional summary is returned. Each search result is a `DeserializedSearchResult` object. More information on types can be found [here](src/types.ts).

##### isLoading: `boolean`

Expand Down
2 changes: 1 addition & 1 deletion docs/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

100 changes: 76 additions & 24 deletions docs/src/components/ConfigurationDrawer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,34 +14,46 @@ type Props = {
isOpen: boolean;
setIsOpen: (isOpen: boolean) => void;
corpusId: string;
onUpdateCorpusId: (event: React.ChangeEvent<HTMLInputElement>) => void;
setCorpusId: (corpusId: string) => void;
customerId: string;
onUpdateCustomerId: (event: React.ChangeEvent<HTMLInputElement>) => void;
setCustomerId: (customerId: string) => void;
apiKey: string;
onUpdateApiKey: (event: React.ChangeEvent<HTMLInputElement>) => void;
setApiKey: (apiKey: string) => void;
placeholder: string;
onUpdatePlaceholder: (event: React.ChangeEvent<HTMLInputElement>) => void;
isDeeplinkable: boolean;
onUpdateIsDeeplinkable: (event: React.ChangeEvent<HTMLInputElement>) => void;
setPlaceholder: (placeholder: string) => void;
isDeepLinkable: boolean;
setIsDeepLinkable: (isDeepLinkable: boolean) => void;
openResultsInNewTab: boolean;
onUpdateOpenResultsInNewTab: (event: React.ChangeEvent<HTMLInputElement>) => void;
isOnToggleSummaryHandled: boolean;
setIsOnToggleSummaryHandled: (isOnToggleSummaryHandled: boolean) => void;
setOpenResultsInNewTab: (openResultsInNewTab: boolean) => void;
isSummaryToggleVisible: boolean;
setIsSummaryToggleVisible: (isSummaryToggleVisible: boolean) => void;
isSummaryToggleInitiallyEnabled: boolean;
setIsSummaryToggleInitiallyEnabled: (isSummaryToggleInitiallyEnabled: boolean) => void;
};

export const ConfigurationDrawer = ({
isOpen,
setIsOpen,
corpusId,
onUpdateCorpusId,
setCorpusId,
customerId,
onUpdateCustomerId,
setCustomerId,
apiKey,
onUpdateApiKey,
setApiKey,
placeholder,
onUpdatePlaceholder,
isDeeplinkable,
onUpdateIsDeeplinkable,
setPlaceholder,
isDeepLinkable,
setIsDeepLinkable,
openResultsInNewTab,
onUpdateOpenResultsInNewTab
setOpenResultsInNewTab,
isOnToggleSummaryHandled,
setIsOnToggleSummaryHandled,
isSummaryToggleVisible,
setIsSummaryToggleVisible,
isSummaryToggleInitiallyEnabled,
setIsSummaryToggleInitiallyEnabled
}: Props) => {
return (
<VuiDrawer
Expand Down Expand Up @@ -71,49 +83,89 @@ export const ConfigurationDrawer = ({
<VuiSpacer size="s" />

<VuiFormGroup label="Customer ID" labelFor="customerId">
<VuiTextInput value={customerId} onChange={onUpdateCustomerId} />
<VuiTextInput value={customerId} onChange={(e) => setCustomerId(e.target.value)} />
</VuiFormGroup>

<VuiSpacer size="xs" />

<VuiFormGroup label="Corpus ID" labelFor="corpusId">
<VuiTextInput value={corpusId} onChange={onUpdateCorpusId} />
<VuiTextInput value={corpusId} onChange={(e) => setCorpusId(e.target.value)} />
</VuiFormGroup>

<VuiSpacer size="xs" />

<VuiFormGroup label="API key" labelFor="apiKey">
<VuiTextInput value={apiKey} onChange={onUpdateApiKey} fullWidth />
<VuiTextInput value={apiKey} onChange={(e) => setApiKey(e.target.value)} fullWidth />
</VuiFormGroup>

<VuiSpacer size="l" />

<VuiTitle size="s">
<h3 className="header">Customize appearance</h3>
<h3 className="header">Search input</h3>
</VuiTitle>

<VuiSpacer size="s" />

<VuiFormGroup label="Placeholder text" labelFor="placeholderText">
<VuiTextInput value={placeholder} onChange={onUpdatePlaceholder} fullWidth />
<VuiTextInput value={placeholder} onChange={(e) => setPlaceholder(e.target.value)} fullWidth />
</VuiFormGroup>

<VuiSpacer size="l" />

<VuiTitle size="s">
<h3 className="header">Customize behavior</h3>
<h3 className="header">Search behavior</h3>
</VuiTitle>

<VuiSpacer size="s" />

<VuiFormGroup label="Allow deeplinking" labelFor="isDeepLinkable">
<VuiToggle checked={isDeeplinkable} onChange={onUpdateIsDeeplinkable} id="isDeeplinkable" />
<VuiFormGroup label="Enable deep-linking to a search" labelFor="isDeepLinkable">
<VuiToggle checked={isDeepLinkable} onChange={(e) => setIsDeepLinkable(e.target.checked)} id="isDeepLinkable" />
</VuiFormGroup>

<VuiSpacer size="xs" />

<VuiFormGroup label="Open results in a new tab" labelFor="openResultsInNewTab">
<VuiToggle checked={openResultsInNewTab} onChange={onUpdateOpenResultsInNewTab} id="openResultsInNewTab" />
<VuiFormGroup label="Open a search result's link in a new tab" labelFor="openResultsInNewTab">
<VuiToggle
checked={openResultsInNewTab}
onChange={(e) => setOpenResultsInNewTab(e.target.checked)}
id="openResultsInNewTab"
/>
</VuiFormGroup>

<VuiSpacer size="l" />

<VuiTitle size="s">
<h3 className="header">Summarization</h3>
</VuiTitle>

<VuiSpacer size="s" />

<VuiFormGroup label="Handle summary toggle change" labelFor="summaryToggleHandler">
<VuiToggle
checked={isOnToggleSummaryHandled}
onChange={(e) => setIsOnToggleSummaryHandled(e.target.checked)}
id="summaryToggleHandler"
/>
</VuiFormGroup>

<VuiSpacer size="xs" />

<VuiFormGroup label="Is summary toggle visible" labelFor="summaryToggleVisible">
<VuiToggle
checked={isSummaryToggleVisible}
onChange={(e) => setIsSummaryToggleVisible(e.target.checked)}
id="summaryToggleVisible"
/>
</VuiFormGroup>

<VuiSpacer size="xs" />

<VuiFormGroup label="Is summary toggle initially enabled" labelFor="summaryToggleInitiallyEnabled">
<VuiToggle
checked={isSummaryToggleInitiallyEnabled}
onChange={(e) => setIsSummaryToggleInitiallyEnabled(e.target.checked)}
id="summaryToggleInitiallyEnabled"
/>
</VuiFormGroup>

<VuiSpacer size="l" />
Expand Down
113 changes: 69 additions & 44 deletions docs/src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeEvent, useCallback, useState } from "react";
import { useState } from "react";
import ReactDOM from "react-dom";
import { BiLogoGithub } from "react-icons/bi";
import { ReactSearch } from "@vectara/react-search";
Expand All @@ -22,14 +22,27 @@ import { ConfigurationDrawer } from "components/ConfigurationDrawer";
import "./ui/_index.scss";
import "./index.scss";

const generateCodeSnippet = (
customerId?: string,
corpusId?: string,
apiKey?: string,
placeholder?: string,
isDeepLinkable: boolean = false,
openResultsInNewTab: boolean = false
) => {
const generateCodeSnippet = ({
customerId,
corpusId,
apiKey,
placeholder,
isDeepLinkable = false,
openResultsInNewTab = false,
isOnToggleSummaryHandled = false,
isSummaryToggleVisible = false,
isSummaryToggleInitiallyEnabled = false
}: {
customerId?: string;
corpusId?: string;
apiKey?: string;
placeholder?: string;
isDeepLinkable: boolean;
openResultsInNewTab: boolean;
isOnToggleSummaryHandled: boolean;
isSummaryToggleVisible: boolean;
isSummaryToggleInitiallyEnabled: boolean;
}) => {
let quotedPlaceholder = placeholder;

if (placeholder) {
Expand All @@ -51,13 +64,25 @@ const generateCodeSnippet = (
}

if (isDeepLinkable) {
props.push(`isDeeplinkable={${isDeepLinkable}}`);
props.push(`isDeepLinkable={${isDeepLinkable}}`);
}

if (openResultsInNewTab) {
props.push(`openResultsInNewTab={${openResultsInNewTab}}`);
}

if (isOnToggleSummaryHandled) {
props.push(`onToggleSummary={(isSummaryEnabled: boolean) => console.log(isSummaryEnabled)}`);
}

if (isSummaryToggleVisible) {
props.push(`isSummaryToggleVisible={${isSummaryToggleVisible}}`);
}

if (isSummaryToggleInitiallyEnabled) {
props.push(`isSummaryToggleInitiallyEnabled={${isSummaryToggleInitiallyEnabled}}`);
}

props.push(`zIndex={ /* (optional) number representing the z-index the search modal should have */ }`);

return `import { ReactSearch } from "@vectara/react-search";
Expand All @@ -82,32 +107,11 @@ const App = () => {
const [customerId, setCustomerId] = useState<string>("");
const [apiKey, setApiKey] = useState<string>("");
const [placeholder, setPlaceholder] = useState<string>(DEFAULT_PLACEHOLDER);
const [isDeeplinkable, setIsDeeplinkable] = useState<boolean>(false);
const [isDeepLinkable, setIsDeepLinkable] = useState<boolean>(false);
const [openResultsInNewTab, setOpenResultsInNewTab] = useState<boolean>(false);

const onUpdateCorpusId = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setCorpusId(e.target.value);
}, []);

const onUpdateCustomerId = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setCustomerId(e.target.value);
}, []);

const onUpdateApiKey = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setApiKey(e.target.value);
}, []);

const onUpdatePlaceholder = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setPlaceholder(e.target.value);
}, []);

const onUpdateIsDeeplinkable = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setIsDeeplinkable(e.target.checked);
}, []);

const onUpdateOpenResultsInNewTab = useCallback((e: ChangeEvent<HTMLInputElement>) => {
setOpenResultsInNewTab(e.target.checked);
}, []);
const [isOnToggleSummaryHandled, setIsOnToggleSummaryHandled] = useState<boolean>(false);
const [isSummaryToggleVisible, setIsSummaryToggleVisible] = useState<boolean>(false);
const [isSummaryToggleInitiallyEnabled, setIsSummaryToggleInitiallyEnabled] = useState<boolean>(false);

return (
<>
Expand Down Expand Up @@ -171,8 +175,13 @@ const App = () => {
customerId={customerId === "" ? DEFAULT_CUSTOMER_ID : customerId}
apiKey={apiKey === "" ? DEFAULT_API_KEY : apiKey}
placeholder={placeholder}
isDeeplinkable={isDeeplinkable}
isDeepLinkable={isDeepLinkable}
openResultsInNewTab={openResultsInNewTab}
isSummaryToggleVisible={isSummaryToggleVisible}
isSummaryToggleInitiallyEnabled={isSummaryToggleInitiallyEnabled}
onToggleSummary={(isSummaryEnabled: boolean) =>
console.log(`onToggleSummary callback received isSummaryEnabled: ${isSummaryEnabled}`)
}
/>
</div>

Expand Down Expand Up @@ -206,7 +215,17 @@ const App = () => {
<VuiSpacer size="s" />

<VuiCode language="tsx">
{generateCodeSnippet(customerId, corpusId, apiKey, placeholder, isDeeplinkable, openResultsInNewTab)}
{generateCodeSnippet({
customerId,
corpusId,
apiKey,
placeholder,
isDeepLinkable,
openResultsInNewTab,
isOnToggleSummaryHandled,
isSummaryToggleVisible,
isSummaryToggleInitiallyEnabled
})}
</VuiCode>

<VuiSpacer size="xxl" />
Expand Down Expand Up @@ -268,17 +287,23 @@ export const App = () => {
isOpen={isConfigurationDrawerOpen}
setIsOpen={setIsConfigurationDrawerOpen}
corpusId={corpusId}
onUpdateCorpusId={onUpdateCorpusId}
setCorpusId={setCorpusId}
customerId={customerId}
onUpdateCustomerId={onUpdateCustomerId}
setCustomerId={setCustomerId}
apiKey={apiKey}
onUpdateApiKey={onUpdateApiKey}
setApiKey={setApiKey}
placeholder={placeholder}
onUpdatePlaceholder={onUpdatePlaceholder}
isDeeplinkable={isDeeplinkable}
onUpdateIsDeeplinkable={onUpdateIsDeeplinkable}
setPlaceholder={setPlaceholder}
isDeepLinkable={isDeepLinkable}
setIsDeepLinkable={setIsDeepLinkable}
openResultsInNewTab={openResultsInNewTab}
onUpdateOpenResultsInNewTab={onUpdateOpenResultsInNewTab}
setOpenResultsInNewTab={setOpenResultsInNewTab}
isOnToggleSummaryHandled={isOnToggleSummaryHandled}
setIsOnToggleSummaryHandled={setIsOnToggleSummaryHandled}
isSummaryToggleVisible={isSummaryToggleVisible}
setIsSummaryToggleVisible={setIsSummaryToggleVisible}
isSummaryToggleInitiallyEnabled={isSummaryToggleInitiallyEnabled}
setIsSummaryToggleInitiallyEnabled={setIsSummaryToggleInitiallyEnabled}
/>
</div>
</VuiAppContent>
Expand Down
Loading

0 comments on commit fec3fa9

Please sign in to comment.