Skip to content

Commit

Permalink
feat(nx-dev): use textarea for prompts and show a better "no results"…
Browse files Browse the repository at this point in the history
…error (#18798)
  • Loading branch information
jaysoo authored Aug 25, 2023
1 parent 3ebb772 commit e4755cb
Show file tree
Hide file tree
Showing 5 changed files with 143 additions and 47 deletions.
59 changes: 46 additions & 13 deletions nx-dev/feature-ai/src/lib/error-message.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,52 @@
import { XCircleIcon } from '@heroicons/react/24/outline';
import {
XCircleIcon,
ExclamationTriangleIcon,
} from '@heroicons/react/24/outline';

export function ErrorMessage({ error }: { error: any }): JSX.Element {
return (
<div className="rounded-md bg-red-50 p-4">
<div className="flex">
<div className="flex-shrink-0">
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
if (error.data.no_results) {
return (
<div className="rounded-md bg-yellow-50 p-4">
<div className="flex">
<div className="flex-shrink-0">
<ExclamationTriangleIcon
className="h-5 w-5 text-yellow-500"
aria-hidden="true"
/>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-yellow-800">
No results found
</h3>
<div className="mt-2 text-sm text-yellow-700">
Sorry, I don't know how to help with that. You can visit the{' '}
<a
href="https://nx.dev/getting-started/intro"
className="underline"
>
Nx documentation
</a>{' '}
for more info.
</div>
</div>
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
Oopsies! I encountered an error
</h3>
<div className="mt-2 text-sm text-red-700">{error['message']}</div>
</div>
);
} else {
return (
<div className="rounded-md bg-red-50 p-4">
<div className="flex">
<div className="flex-shrink-0">
<XCircleIcon className="h-5 w-5 text-red-400" aria-hidden="true" />
</div>
<div className="ml-3">
<h3 className="text-sm font-medium text-red-800">
Oopsies! I encountered an error
</h3>
<div className="mt-2 text-sm text-red-700">{error['message']}</div>
</div>
</div>
</div>
</div>
);
);
}
}
16 changes: 4 additions & 12 deletions nx-dev/feature-ai/src/lib/feed-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import {
ChatItem,
getProcessedHistory,
queryAi,
resetHistory,
sendFeedbackAnalytics,
sendQueryAnalytics,
} from '@nx/nx-dev/data-access-ai';
Expand All @@ -12,7 +11,6 @@ import { ErrorMessage } from './error-message';
import { Feed } from './feed/feed';
import { LoadingState } from './loading-state';
import { Prompt } from './prompt';
import { WarningMessage } from './sidebar/warning-message';
import { formatMarkdownSources } from './utils';

interface LastQueryMetadata {
Expand All @@ -33,7 +31,7 @@ const assistantWelcome: ChatItem = {

export function FeedContainer(): JSX.Element {
const [chatHistory, setChatHistory] = useState<ChatItem[]>([]);
const [hasError, setHasError] = useState<any | null>(null);
const [queryError, setQueryError] = useState<any | null>(null);
const [isLoading, setIsLoading] = useState(false);
const [lastQueryMetadata, setLastQueryMetadata] =
useState<LastQueryMetadata | null>(null);
Expand All @@ -54,7 +52,7 @@ export function FeedContainer(): JSX.Element {
currentHistory.push({ role: 'user', content: query });

setIsLoading(true);
setHasError(null);
setQueryError(null);

try {
const lastAnswerChatItem =
Expand Down Expand Up @@ -94,7 +92,7 @@ export function FeedContainer(): JSX.Element {
...aiResponse.usage,
});
} catch (error: any) {
setHasError(error);
setQueryError(error);
}

setIsLoading(false);
Expand Down Expand Up @@ -122,12 +120,6 @@ export function FeedContainer(): JSX.Element {
});
};

const handleReset = () => {
resetHistory();
setChatHistory([]);
setHasError(null);
};

return (
<>
{/*WRAPPER*/}
Expand Down Expand Up @@ -158,7 +150,7 @@ export function FeedContainer(): JSX.Element {
/>

{isLoading && <LoadingState />}
{hasError && <ErrorMessage error={hasError} />}
{queryError && <ErrorMessage error={queryError} />}

<div className="sticky bottom-0 left-0 right-0 w-full pt-6 pb-4 bg-gradient-to-t from-white via-white dark:from-slate-900 dark:via-slate-900">
<Prompt
Expand Down
75 changes: 53 additions & 22 deletions nx-dev/feature-ai/src/lib/prompt.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { useEffect, useRef, useState } from 'react';
import { PaperAirplaneIcon } from '@heroicons/react/24/outline';
import { Button } from '@nx/nx-dev/ui-common';
import Textarea from 'react-textarea-autosize';

export function Prompt({
isDisabled,
Expand All @@ -8,35 +10,64 @@ export function Prompt({
isDisabled: boolean;
handleSubmit: (query: string) => void;
}) {
const formRef = useRef<HTMLFormElement>(null);
const inputRef = useRef<HTMLTextAreaElement>(null);
const [inputValue, setInputValue] = useState<string>('');

useEffect(() => {
if (inputRef.current) {
inputRef.current.focus();
}
}, []);

return (
<form
ref={formRef}
onSubmit={(event) => {
event.preventDefault();
handleSubmit((event.target as any).query.value);
if (!inputValue?.trim()) return;
handleSubmit(inputValue);
setInputValue('');
event.currentTarget.reset();
}}
className="relative flex gap-4 max-w-xl mx-auto py-2 px-4 shadow-lg rounded-md border border-slate-300 bg-white dark:border-slate-900 dark:bg-slate-700"
className="relative flex gap-2 max-w-2xl mx-auto py-0 px-2 shadow-lg rounded-md border border-slate-300 bg-white dark:border-slate-900 dark:bg-slate-700"
>
<input
id="query-prompt"
name="query"
disabled={isDisabled}
className="p-0 flex flex-grow text-sm placeholder-slate-500 transition bg-transparent focus:placeholder-slate-400 dark:focus:placeholder-slate-300 dark:text-white focus:outline-none focus:ring-0 border-none disabled:cursor-not-allowed"
placeholder="How does caching work?"
type="text"
/>
<Button
variant="primary"
size="small"
type="submit"
disabled={isDisabled}
className="disabled:cursor-not-allowed"
>
<div hidden className="sr-only">
Ask
</div>
<PaperAirplaneIcon aria-hidden="true" className="h-5 w-5" />
</Button>
<div className="overflow-y-auto w-full h-full max-h-[300px]">
<Textarea
onKeyDown={(event) => {
if (
event.key === 'Enter' &&
!event.shiftKey &&
!event.nativeEvent.isComposing
) {
formRef.current?.requestSubmit();
event.preventDefault();
}
}}
ref={inputRef}
onChange={(event) => setInputValue(event.target.value)}
id="query-prompt"
name="query"
disabled={isDisabled}
className="block w-full p-0 resize-none bg-transparent text-sm placeholder-slate-500 pl-2 py-[1.3rem] focus-within:outline-none focus:placeholder-slate-400 dark:focus:placeholder-slate-300 dark:text-white focus:outline-none focus:ring-0 border-none disabled:cursor-not-allowed"
placeholder="How does caching work?"
rows={1}
/>
</div>
<div className="flex pb-2">
<Button
variant="primary"
size="small"
type="submit"
disabled={isDisabled}
className="self-end w-12 h-12 disabled:cursor-not-allowed"
>
<div hidden className="sr-only">
Ask
</div>
<PaperAirplaneIcon aria-hidden="true" className="h-5 w-5" />
</Button>
</div>
</form>
);
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
"react-redux": "8.0.5",
"react-refresh": "^0.10.0",
"react-router-dom": "^6.11.2",
"react-textarea-autosize": "^8.3.0",
"regenerator-runtime": "0.13.7",
"resolve.exports": "1.1.0",
"rollup": "^2.56.2",
Expand Down
39 changes: 39 additions & 0 deletions pnpm-lock.yaml

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

1 comment on commit e4755cb

@vercel
Copy link

@vercel vercel bot commented on e4755cb Aug 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

nx-dev – ./

nx-dev-nrwl.vercel.app
nx-five.vercel.app
nx-dev-git-master-nrwl.vercel.app
nx.dev

Please sign in to comment.