Skip to content

Commit 94ddc56

Browse files
Bogdan TsechoevTanya301
Bogdan Tsechoev
authored andcommitted
Bot UI: Hint cards
1 parent 78f8262 commit 94ddc56

File tree

11 files changed

+231
-5
lines changed

11 files changed

+231
-5
lines changed

ui/cspell.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,7 @@
199199
"tsql",
200200
"TSQL",
201201
"sparql",
202-
"SPARQL"
202+
"SPARQL",
203+
"subtransactions"
203204
]
204205
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import type { SVGProps } from 'react'
2+
import React from 'react'
3+
4+
export function ArrowGrowthIcon() {
5+
return (
6+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 140 140">
7+
<path
8+
stroke="#AF52DE"
9+
strokeLinecap="round"
10+
strokeLinejoin="round"
11+
strokeWidth="4"
12+
d="M134.167 35 78.7507 90.4167 49.584 61.25 5.83398 105M134.167 35H99.1673m34.9997 0v35"
13+
/>
14+
</svg>)
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react'
2+
3+
export const CommonTypeIcon = () => {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 140 140">
6+
<path
7+
stroke="#AF52DE"
8+
strokeLinecap="round"
9+
strokeLinejoin="round"
10+
strokeWidth="4"
11+
d="M69.9993 11.667v23.3333m0 69.9997v23.334M28.7577 28.7587 45.266 45.267m49.4667 49.4667 16.5083 16.5083M11.666 70.0003h23.3333m69.9997 0h23.334M28.7577 111.242 45.266 94.7337M94.7327 45.267l16.5083-16.5083" />
12+
</svg>
13+
)
14+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import React from 'react'
2+
import { Hint } from 'pages/Bot/hints'
3+
import { matchHintTypeAndIcon } from "../../utils";
4+
import { makeStyles } from "@material-ui/core";
5+
import { useAiBot } from "../../hooks";
6+
7+
const useStyles = makeStyles((theme) => ({
8+
container: {
9+
backgroundColor: 'transparent',
10+
border: '1px solid rgba(0, 0, 0, 0.25)',
11+
borderRadius: '0.5rem',
12+
display: 'flex',
13+
flexDirection: 'column',
14+
alignItems: 'flex-start',
15+
cursor: 'pointer',
16+
width: '11rem',
17+
height: '6rem',
18+
padding: '0.5rem',
19+
color: 'black',
20+
textAlign: 'left',
21+
fontSize: '0.938rem',
22+
transition: '0.2s ease-in',
23+
24+
'& svg': {
25+
width: '22px',
26+
height: '22px',
27+
marginBottom: '0.5rem',
28+
'& path': {
29+
stroke: 'black',
30+
},
31+
[theme.breakpoints.down('sm')]: {
32+
width: '16px',
33+
height: '16px'
34+
}
35+
},
36+
37+
'&:hover, &:focus-visible': {
38+
border: '1px solid rgba(0, 0, 0, 0.8)',
39+
},
40+
[theme.breakpoints.down(1024)]: {
41+
flex: '1 1 45%',
42+
},
43+
[theme.breakpoints.down(480)]: {
44+
margin: '0 0.5rem',
45+
fontSize: '0.813rem',
46+
height: 'auto',
47+
},
48+
},
49+
}));
50+
51+
export const HintCard = (props: Hint & {orgId: number}) => {
52+
const { prompt, hint, type, orgId } = props;
53+
const { sendMessage, chatVisibility } = useAiBot();
54+
55+
const classes = useStyles();
56+
57+
const handleSendMessage = async () => {
58+
await sendMessage({
59+
content: prompt,
60+
org_id: orgId,
61+
is_public: chatVisibility === 'public'
62+
})
63+
}
64+
65+
return (
66+
<button
67+
onClick={handleSendMessage}
68+
className={classes.container}
69+
>
70+
{React.createElement(matchHintTypeAndIcon(type))}
71+
<span>
72+
{hint}
73+
</span>
74+
</button>
75+
)
76+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from 'react'
2+
import { hints } from '../hints'
3+
import { HintCard } from "./HintCard/HintCard";
4+
import { makeStyles } from "@material-ui/core";
5+
6+
const useStyles = makeStyles((theme) => ({
7+
container: {
8+
display: 'flex',
9+
flexWrap: 'wrap',
10+
justifyContent: 'space-around',
11+
gap: '.5rem',
12+
marginTop: '2rem',
13+
[theme.breakpoints.down(1200)]: {
14+
justifyContent: 'center',
15+
},
16+
[theme.breakpoints.down(480)]: {
17+
marginBottom: '1.5rem',
18+
},
19+
[theme.breakpoints.down(760)]: {
20+
'& > *:nth-child(n+3)': {
21+
display: 'none',
22+
},
23+
},
24+
},
25+
}));
26+
27+
export const HintCards = React.memo(({orgId}: {orgId: number}) => {
28+
const classes = useStyles();
29+
return (
30+
<div className={classes.container}>
31+
{
32+
hints.map((hint) => <HintCard key={hint.hint} {...hint} orgId={orgId} />)
33+
}
34+
</div>
35+
)
36+
})
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import React from 'react'
2+
3+
export const TableIcon = () => {
4+
return (
5+
<svg
6+
xmlns="http://www.w3.org/2000/svg"
7+
fill="none"
8+
viewBox="0 0 180 180"
9+
>
10+
<path
11+
stroke="#AF52DE"
12+
strokeLinecap="round"
13+
strokeLinejoin="round"
14+
strokeWidth="4"
15+
d="M67.5 22.5h-30c-3.9782 0-7.7936 1.5804-10.6066 4.3934C24.0804 29.7064 22.5 33.5218 22.5 37.5v30m45-45h75c3.978 0 7.794 1.5804 10.607 4.3934 2.813 2.813 4.393 6.6284 4.393 10.6066v30m-90-45v135m-45-90v75c0 3.978 1.5804 7.794 4.3934 10.607 2.813 2.813 6.6284 4.393 10.6066 4.393h30m-45-90h135m0 0v75c0 3.978-1.58 7.794-4.393 10.607-2.813 2.813-6.629 4.393-10.607 4.393h-75"
16+
/>
17+
</svg>
18+
)
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import React from 'react'
2+
3+
export const WrenchIcon = () => {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 140 140">
6+
<path
7+
stroke="#AF52DE"
8+
strokeLinecap="round"
9+
strokeLinejoin="round"
10+
strokeWidth="4"
11+
d="M85.7499 36.7501c-1.0688 1.0904-1.6675 2.5564-1.6675 4.0833 0 1.5269.5987 2.9929 1.6675 4.0834l9.3333 9.3333c1.0904 1.0688 2.5565 1.6675 4.0834 1.6675 1.5264 0 2.9924-.5987 4.0834-1.6675l21.992-21.9917c2.933 6.482 3.821 13.7039 2.546 20.7034-1.276 6.9995-4.654 13.444-9.685 18.4749-5.031 5.0309-11.475 8.4091-18.4748 9.6844-6.9994 1.2753-14.2214.3872-20.7033-2.546L38.6166 118.883c-2.3207 2.321-5.4682 3.625-8.75 3.625-3.2819 0-6.4294-1.304-8.75-3.625-2.3207-2.32-3.6244-5.468-3.6244-8.75 0-3.281 1.3037-6.429 3.6244-8.75l40.3083-40.3079c-2.9332-6.4819-3.8213-13.7039-2.546-20.7034 1.2753-6.9994 4.6535-13.444 9.6844-18.4749 5.0308-5.0309 11.4754-8.4091 18.4749-9.6844 6.9995-1.2753 14.2218-.3872 20.7038 2.546L85.7499 36.7501Z" />
12+
</svg>
13+
)
14+
}

ui/packages/platform/src/pages/Bot/Messages/Messages.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ import {PageSpinner} from "@postgres.ai/shared/components/PageSpinner";
1414
import { usePrev } from 'hooks/usePrev';
1515
import { getMaxScrollTop, getUserMessagesCount } from './utils';
1616
import Format from "../../../utils/format";
17-
import { BotMessage, BotMessageWithDebugInfo } from "../../../types/api/entities/bot";
17+
import { BotMessage } from "../../../types/api/entities/bot";
1818
import { Message } from "./Message/Message";
1919
import { useAiBot } from "../hooks";
20+
import { HintCards } from "../HintCards/HintCards";
2021

2122
const useStyles = makeStyles(
2223
(theme) => ({
@@ -119,7 +120,7 @@ type FormattedTime = {
119120
[id: string]: Time
120121
}
121122

122-
export const Messages = React.memo(() => {
123+
export const Messages = React.memo(({orgId}: {orgId: number}) => {
123124
const {
124125
messages,
125126
loading: isLoading,
@@ -225,6 +226,7 @@ export const Messages = React.memo(() => {
225226
Consider checking important information. <br />
226227
Depending on settings, LLM service provider such as GCP or OpenAI is used.
227228
</Typography>
229+
<HintCards orgId={orgId} />
228230
</div>
229231
)
230232
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
export type HintType = 'design' | 'settings' | 'performance' | 'common'
2+
3+
export type Hint = {
4+
hint: string,
5+
prompt: string,
6+
type: HintType
7+
}
8+
9+
export const hints: Hint[] = [
10+
{
11+
hint: 'Help me design an IoT system DB schema',
12+
prompt: 'Help me design an IoT system DB schema',
13+
type: 'design'
14+
},
15+
{
16+
hint: 'Should I enable wal_compression?',
17+
prompt: 'Should I enable wal_compression?',
18+
type: 'settings',
19+
},
20+
{
21+
hint: 'Demonstrate benefits of Index-Only Scans',
22+
prompt: 'Show the benefits of Index-Only Scans. Invent a test case, create two types of queries, run them on Postgres 16, and show the plans. Then explain the difference.',
23+
type: 'performance',
24+
},
25+
{
26+
hint: 'What do people say about subtransactions?',
27+
prompt: 'What do people say about subtransactions?',
28+
type: 'common'
29+
},
30+
]

ui/packages/platform/src/pages/Bot/index.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ export const BotPage = (props: BotPageProps) => {
226226
</Box>
227227
</Box>
228228
<Box className={cn(classes.contentContainer, {[classes.isChatsListVisible]: isChatsListVisible})}>
229-
<Messages />
229+
<Messages orgId={orgData.id} />
230230
<Command
231231
threadId={match.params.threadId}
232232
orgId={orgData.id}

ui/packages/platform/src/pages/Bot/utils.ts

+20-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
*/
77

88
import { API_URL_PREFIX } from "../../config/env";
9-
import { BotMessage, BotMessageWithDebugInfo, DebugMessage } from "../../types/api/entities/bot";
9+
import { DebugMessage } from "../../types/api/entities/bot";
10+
import { HintType } from "./hints";
11+
import { FunctionComponent } from "react";
12+
import { ArrowGrowthIcon } from "./HintCards/ArrowGrowthIcon/ArrowGrowthIcon";
13+
import { WrenchIcon } from "./HintCards/WrenchIcon/WrenchIcon";
14+
import { TableIcon } from "./HintCards/TableIcon/TableIcon";
15+
import { CommonTypeIcon } from "./HintCards/CommonTypeIcon/CommonTypeIcon";
1016

1117
export const permalinkLinkBuilder = (id: string): string => {
1218
const apiUrl = process.env.REACT_APP_API_URL_PREFIX || API_URL_PREFIX;
@@ -91,4 +97,17 @@ export const formatLanguageName = (language: string): string => {
9197
} else {
9298
return language.charAt(0).toUpperCase() + language.slice(1).toLowerCase();
9399
}
100+
}
101+
102+
export function matchHintTypeAndIcon(hintType: HintType): FunctionComponent<SVGElement> {
103+
switch (hintType) {
104+
case 'performance':
105+
return ArrowGrowthIcon
106+
case 'settings':
107+
return WrenchIcon
108+
case 'design':
109+
return TableIcon
110+
default:
111+
return CommonTypeIcon
112+
}
94113
}

0 commit comments

Comments
 (0)