-
Notifications
You must be signed in to change notification settings - Fork 4.5k
chore: Update markdown component + create avatar component + refactor #36832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
371507d
a0fdc7e
62e473c
116da06
1e0640f
0227e86
c3e2a83
a55e8ba
34efee9
108540b
211357f
c052a50
60d12dc
906b65c
72dabf2
57c8549
db2bc5c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,62 @@ | ||
| import React, { useState } from "react"; | ||
| import { | ||
| Avatar, | ||
| Button, | ||
| Flex, | ||
| Modal, | ||
| ModalBody, | ||
| ModalContent, | ||
| ModalHeader, | ||
| Text, | ||
| } from "@appsmith/wds"; | ||
|
|
||
| import styles from "./styles.module.css"; | ||
|
|
||
| // this value might come from props in future. So keeping a temporary value here. | ||
| const LOGO = | ||
| "https://app.appsmith.com/static/media/appsmith_logo_square.3867b1959653dabff8dc.png"; | ||
|
Comment on lines
+1
to
+17
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Class, let's discuss the imports and constants! Good job on organizing your imports, but I have a small suggestion for you. The Consider moving the
export const LOGO = "https://app.appsmith.com/static/media/appsmith_logo_square.3867b1959653dabff8dc.png";
import { LOGO } from './constants';Remember, good organization is key to writing maintainable code! |
||
|
|
||
| export const ChatHeader: React.FC<{ | ||
| chatTitle?: string; | ||
| username: string; | ||
| chatDescription?: string; | ||
| }> = ({ chatDescription, chatTitle, username }) => { | ||
| const [isChatDescriptionModalOpen, setIsChatDescriptionModalOpen] = | ||
| useState(false); | ||
|
|
||
| return ( | ||
| <> | ||
| <div className={styles.header}> | ||
| <Flex alignItems="center" gap="spacing-2"> | ||
| <Flex alignItems="center" gap="spacing-3"> | ||
| <Avatar label="Appsmith AI" size="large" src={LOGO} /> | ||
| <Text fontWeight={600} size="subtitle"> | ||
| {chatTitle} | ||
| </Text> | ||
| </Flex> | ||
| <Button | ||
| icon="info-square-rounded" | ||
| onPress={() => setIsChatDescriptionModalOpen(true)} | ||
| variant="ghost" | ||
| /> | ||
| </Flex> | ||
| <Flex alignItems="center" gap="spacing-2"> | ||
| <Avatar label={username} /> | ||
| <Text data-testid="t--aichat-username" size="body"> | ||
| {username} | ||
| </Text> | ||
| </Flex> | ||
| </div> | ||
|
|
||
| <Modal | ||
| isOpen={isChatDescriptionModalOpen} | ||
| setOpen={setIsChatDescriptionModalOpen} | ||
| > | ||
| <ModalContent> | ||
| <ModalHeader title="Information about the bot" /> | ||
| <ModalBody>{chatDescription}</ModalBody> | ||
| </ModalContent> | ||
| </Modal> | ||
| </> | ||
| ); | ||
| }; | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,48 @@ | ||
| import React from "react"; | ||
| import { Flex, ChatInput, Icon, Text } from "@appsmith/wds"; | ||
|
|
||
| const MIN_PROMPT_LENGTH = 3; | ||
|
|
||
| export const ChatInputSection: React.FC<{ | ||
| isWaitingForResponse: boolean; | ||
| prompt: string; | ||
| promptInputPlaceholder?: string; | ||
| onPromptChange: (value: string) => void; | ||
| onSubmit?: () => void; | ||
| }> = ({ | ||
| isWaitingForResponse, | ||
| onPromptChange, | ||
| onSubmit, | ||
| prompt, | ||
| promptInputPlaceholder, | ||
| }) => ( | ||
| <Flex | ||
| direction="column" | ||
| gap="spacing-3" | ||
| paddingBottom="spacing-4" | ||
| paddingLeft="spacing-6" | ||
| paddingRight="spacing-6" | ||
| paddingTop="spacing-4" | ||
| > | ||
| <ChatInput | ||
| isLoading={isWaitingForResponse} | ||
| isSubmitDisabled={prompt.length < MIN_PROMPT_LENGTH} | ||
| onChange={onPromptChange} | ||
| onSubmit={onSubmit} | ||
| placeholder={promptInputPlaceholder} | ||
| value={prompt} | ||
| /> | ||
| <Flex | ||
| alignItems="center" | ||
| flexGrow={1} | ||
| gap="spacing-1" | ||
| justifyContent="center" | ||
| > | ||
| <Icon name="alert-circle" size="small" /> | ||
| <Text color="neutral" size="caption" textAlign="center"> | ||
| LLM assistant can make mistakes. Answers should be verified before they | ||
| are trusted. | ||
| </Text> | ||
| </Flex> | ||
| </Flex> | ||
| ); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| import React from "react"; | ||
| import { Avatar, Flex, Markdown } from "@appsmith/wds"; | ||
|
|
||
| import styles from "./styles.module.css"; | ||
| import type { ChatMessage } from "./types"; | ||
| import { AssistantSuggestionButton } from "./AssistantSuggestionButton"; | ||
|
|
||
| export const ChatThread: React.FC<{ | ||
| thread: ChatMessage[]; | ||
| onApplyAssistantSuggestion?: (suggestion: string) => void; | ||
| username: string; | ||
| }> = ({ onApplyAssistantSuggestion, thread, username }) => ( | ||
| <Flex direction="column" gap="spacing-3" padding="spacing-6"> | ||
| {thread.map((message: ChatMessage) => { | ||
| const { content, isAssistant, promptSuggestions = [] } = message; | ||
|
|
||
| return ( | ||
| <Flex direction={isAssistant ? "row" : "row-reverse"} key={message.id}> | ||
| {isAssistant && ( | ||
| <div> | ||
| <Markdown>{content}</Markdown> | ||
|
|
||
| {promptSuggestions.length > 0 && ( | ||
| <Flex | ||
| className={styles.suggestions} | ||
| gap="spacing-5" | ||
| paddingTop="spacing-4" | ||
| wrap="wrap" | ||
| > | ||
| {promptSuggestions.map((suggestion) => ( | ||
| <AssistantSuggestionButton | ||
| key={suggestion} | ||
| // eslint-disable-next-line react-perf/jsx-no-new-function-as-prop | ||
| onPress={() => onApplyAssistantSuggestion?.(suggestion)} | ||
| > | ||
| {suggestion} | ||
| </AssistantSuggestionButton> | ||
| ))} | ||
|
Comment on lines
+30
to
+38
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's optimize your suggestion buttons, students! Your implementation of the AssistantSuggestionButton is quite good, like a well-written essay. However, there's room for improvement in how we handle the onPress event. Remember our lesson on callback functions? Using inline functions can cause unnecessary re-renders, like rewriting your entire essay when you only need to change a single word! Let's optimize this by using the useCallback hook: import React, { useCallback } from 'react';
// ... in your component
const handleSuggestionPress = useCallback((suggestion: string) => {
onApplyAssistantSuggestion?.(suggestion);
}, [onApplyAssistantSuggestion]);
// ... in your JSX
<AssistantSuggestionButton
key={suggestion}
onPress={() => handleSuggestionPress(suggestion)}
>
{suggestion}
</AssistantSuggestionButton>This way, we're creating a stable callback function, like using a template for your essays - efficient and consistent! |
||
| </Flex> | ||
| )} | ||
| </div> | ||
| )} | ||
| {!isAssistant && ( | ||
| <Flex direction="row-reverse" gap="spacing-3"> | ||
| <Avatar label={username} /> | ||
| <div>{content}</div> | ||
| </Flex> | ||
| )} | ||
| </Flex> | ||
| ); | ||
| })} | ||
| </Flex> | ||
| ); | ||
This file was deleted.
This file was deleted.
This file was deleted.
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed to handle the table in markdown.