Skip to content

Commit 25e596f

Browse files
author
kim
committed
feat: improve initialPrompt structure and view settings layout
1 parent 2b7d7a5 commit 25e596f

File tree

9 files changed

+61
-118
lines changed

9 files changed

+61
-118
lines changed

cypress/e2e/builder/main.cy.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ describe('Builder View', () => {
8383
// show default values
8484
cy.get(buildDataCy(CHATBOT_SETTINGS_SUMMARY_CY))
8585
.should('contain', MOCK_APP_SETTING.data.chatbotName)
86-
.should('contain', MOCK_APP_SETTING.data.initialPrompt[0].content)
86+
.should('contain', MOCK_APP_SETTING.data.initialPrompt)
8787
.should('contain', MOCK_APP_SETTING.data.chatbotCue);
8888

8989
cy.get(EDIT_SETTINGS_BUTTON).click();

cypress/fixtures/mockSettings.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import { ChatbotRole } from '@graasp/sdk';
2-
31
import { SettingsKeys } from '@/config/appSetting';
42

53
import { MOCK_SERVER_ITEM } from './mockItem';
@@ -13,6 +11,6 @@ export const MOCK_APP_SETTING = {
1311
data: {
1412
chatbotCue: 'cue',
1513
chatbotName: 'name',
16-
initialPrompt: [{ role: ChatbotRole.Assistant, content: 'prompt' }],
14+
initialPrompt: 'prompt',
1715
},
1816
};

src/config/appSetting.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import type { ChatBotMessage } from '@graasp/sdk';
2-
31
export const SettingsKeys = {
42
ChatbotPrompt: 'chatbot-prompt',
53
} as const;
@@ -14,7 +12,7 @@ export const ChatbotPromptSettingsKeys = {
1412
} as const;
1513

1614
export type ChatbotPromptSettings = {
17-
[ChatbotPromptSettingsKeys.InitialPrompt]: ChatBotMessage[];
15+
[ChatbotPromptSettingsKeys.InitialPrompt]: string;
1816
[ChatbotPromptSettingsKeys.ChatbotCue]: string;
1917
[ChatbotPromptSettingsKeys.ChatbotName]: string;
2018
// used to allow access using settings[settingKey] syntax

src/langs/en.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,7 @@
2323
"SEND_LABEL": "Send",
2424
"CHATBOT_NAME_LABEL": "Chatbot Name",
2525
"CHATBOT_NAME_HELPER": "This is the name that users will see when they interact with the chatbot",
26-
"CHATBOT_NAME_DEFAULT_MESSAGE": "by default",
27-
"CHATBOT_VERSION_DEFAULT_MESSAGE": "by default",
26+
"CHATBOT_NAME_DEFAULT_MESSAGE": "(default)",
2827
"CHATBOT_PROMPT_LABEL": "Chatbot Prompt",
2928
"CHATBOT_PROMPT_HELPER_LABEL": "In-depth technical description",
3029
"CHATBOT_PROMPT_HELPER": "This defines the chatbot's personality and how it should behave.",
@@ -33,7 +32,7 @@
3332
"CHATBOT_PROMPT_API_REFERENCE": "See the API reference",
3433
"CHATBOT_CUE_LABEL": "Conversation Starter",
3534
"CHATBOT_CUE_HELPER": "This defines the content of the first message of the chatbot. You can change it to better orient the conversation.",
36-
"CHATBOT_CUE_EMPTY_MESSAGE": "The cue is empty.",
35+
"CHATBOT_CUE_EMPTY_MESSAGE": "The conversation starter is empty.",
3736
"SAVE_LABEL": "Save",
3837
"SAVED_LABEL": "Saved",
3938
"GENERAL_SETTING_TITLE": "General",

src/modules/common/TextArea.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ export const TextArea = styled(TextareaAutosize)(({ theme }) => ({
2424
outline: 'solid var(--graasp-primary) 1px ',
2525
},
2626
fontFamily: 'unset',
27+
lineHeight: 'unset',
2728
}));

src/modules/common/useAskChatbot.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { useCallback } from 'react';
22

33
import { ChatbotThreadMessage, buildPrompt } from '@graasp/apps-query-client';
4+
import { ChatbotRole } from '@graasp/sdk';
45

56
import { AppActionsType } from '@/config/appActions';
67
import { AppDataTypes } from '@/config/appData';
@@ -32,7 +33,7 @@ export const useAskChatbot = (chatbotPrompt: ChatbotPromptSettings) => {
3233

3334
const prompt = [
3435
// this is to spread the JSON setting before the messages
35-
...chatbotPrompt.initialPrompt,
36+
{ role: ChatbotRole.System, content: chatbotPrompt.initialPrompt },
3637
// this function requests the prompt as the first argument in string format
3738
// we can not use it in this context as we are using a JSON prompt.
3839
// if we simplify the prompt in the future we will be able to remove the line above

src/modules/settings/ChatbotSettings.tsx

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
Card,
88
CardContent,
99
FormLabel,
10+
Grid2,
1011
Stack,
1112
Typography,
1213
} from '@mui/material';
@@ -33,8 +34,7 @@ const useChatbotSetting = () => {
3334
const chatbotCue = setting?.data?.chatbotCue ?? '';
3435
const chatbotName = setting?.data?.chatbotName ?? DEFAULT_BOT_USERNAME;
3536

36-
const initialPrompt = setting?.data?.initialPrompt ?? [];
37-
const chatbotPrompt = initialPrompt[0]?.content ?? '';
37+
const initialPrompt = setting?.data?.initialPrompt ?? '';
3838

3939
const saveSetting = useCallback(
4040
async (data: ChatbotPromptSettings): Promise<void> => {
@@ -54,18 +54,17 @@ const useChatbotSetting = () => {
5454
);
5555

5656
return {
57-
chatbotPrompt,
57+
initialPrompt,
5858
chatbotCue,
5959
chatbotName,
60-
initialPrompt,
6160
saveSetting,
6261
};
6362
};
6463

6564
function ChatbotSettings() {
6665
const { t } = useTranslation();
6766

68-
const { saveSetting, chatbotCue, chatbotName, chatbotPrompt, initialPrompt } =
67+
const { saveSetting, chatbotCue, chatbotName, initialPrompt } =
6968
useChatbotSetting();
7069

7170
const [isEditing, setIsEditing] = useState(false);
@@ -109,7 +108,7 @@ function ChatbotSettings() {
109108
{isEditing ? t('CANCEL_LABEL') : t('EDIT_LABEL')}
110109
</Button>
111110
</Stack>
112-
{!chatbotPrompt && (
111+
{!initialPrompt && (
113112
<Alert severity="warning">{t('CHATBOT_CONFIGURATION_MISSING')}</Alert>
114113
)}
115114

@@ -118,7 +117,7 @@ function ChatbotSettings() {
118117
initialValue={{
119118
name: chatbotName,
120119
cue: chatbotCue,
121-
prompt: chatbotPrompt,
120+
prompt: initialPrompt,
122121
}}
123122
onSave={handleOnSave}
124123
/>
@@ -129,44 +128,47 @@ function ChatbotSettings() {
129128
data-cy={CHATBOT_SETTINGS_SUMMARY_CY}
130129
>
131130
<CardContent sx={{ pb: 0 }}>
132-
<Stack direction="column" spacing={1}>
133-
<Stack direction="column">
134-
<Stack direction="row" spacing={1}>
135-
<FormLabel>
136-
<Typography>{t('CHATBOT_NAME_LABEL')}:</Typography>
137-
</FormLabel>
131+
<Grid2 container rowGap={2} spacing={1}>
132+
<Grid2 size={{ xs: 12, sm: 4 }}>
133+
<FormLabel sx={{ fontWeight: 'bold' }}>
134+
{t('CHATBOT_NAME_LABEL')}
135+
</FormLabel>
136+
</Grid2>
137+
<Grid2 size={{ xs: 12, sm: 8 }}>
138+
<Stack direction="row" gap={1}>
138139
<Typography>{chatbotName}</Typography>
139-
{chatbotName === DEFAULT_BOT_USERNAME ? (
140+
{chatbotName === DEFAULT_BOT_USERNAME && (
140141
<Typography color="text.disabled">
141-
({t('CHATBOT_NAME_DEFAULT_MESSAGE')})
142+
{t('CHATBOT_NAME_DEFAULT_MESSAGE')}
142143
</Typography>
143-
) : undefined}
144-
</Stack>
145-
<Typography variant="caption" color="text.secondary">
146-
{t('CHATBOT_NAME_HELPER')}
147-
</Typography>
148-
</Stack>
149-
150-
<Stack direction="column">
151-
<FormLabel>{t('CHATBOT_PROMPT_LABEL')}</FormLabel>
152-
<ChatbotPromptDisplay messages={initialPrompt} />
153-
</Stack>
154-
<Stack direction="column">
155-
<Stack>
156-
<FormLabel>{t('CHATBOT_CUE_LABEL')}:</FormLabel>
157-
<Typography variant="caption" color="text.secondary">
158-
{t('CHATBOT_CUE_HELPER')}
159-
</Typography>
144+
)}
160145
</Stack>
146+
</Grid2>
147+
148+
<Grid2 size={{ xs: 12, sm: 4 }}>
149+
<FormLabel sx={{ fontWeight: 'bold' }}>
150+
{t('CHATBOT_PROMPT_LABEL')}
151+
</FormLabel>
152+
</Grid2>
153+
<Grid2 size={{ xs: 12, sm: 8 }}>
154+
<ChatbotPromptDisplay prompt={initialPrompt} />
155+
</Grid2>
156+
157+
<Grid2 size={{ xs: 12, sm: 4 }}>
158+
<FormLabel sx={{ fontWeight: 'bold' }}>
159+
{t('CHATBOT_CUE_LABEL')}
160+
</FormLabel>
161+
</Grid2>
162+
<Grid2 size={{ xs: 12, sm: 8 }}>
161163
{chatbotCue ? (
162164
<Typography>{chatbotCue}</Typography>
163165
) : (
164166
<Typography color="text.disabled" fontStyle="italic">
165167
{t('CHATBOT_CUE_EMPTY_MESSAGE')}
166168
</Typography>
167169
)}
168-
</Stack>
169-
</Stack>
170+
</Grid2>
171+
</Grid2>
170172
</CardContent>
171173
</Card>
172174
)}

src/modules/settings/chatbot/ChatbotEditingView.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ import { useTranslation } from 'react-i18next';
44

55
import { Box, Button, Stack, TextField } from '@mui/material';
66

7-
import { ChatbotRole } from '@graasp/sdk';
8-
97
import type { ChatbotPromptSettings } from '@/config/appSetting';
108
import ChatbotAvatar from '@/modules/common/ChatbotAvatar';
119
import { TextArea } from '@/modules/common/TextArea';
@@ -50,7 +48,7 @@ function ChatbotEditionView({
5048
const handleSave = (): void => {
5149
if (prompt) {
5250
const data: ChatbotPromptSettings = {
53-
initialPrompt: [{ role: ChatbotRole.System, content: prompt }],
51+
initialPrompt: prompt,
5452
chatbotCue: cue,
5553
chatbotName: name,
5654
};
Lines changed: 16 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,28 @@
11
import type { JSX } from 'react';
2+
import { useTranslation } from 'react-i18next';
23

3-
import { Box, Paper, Stack, Typography } from '@mui/material';
4-
5-
import { ChatBotMessage, ChatbotRole, ChatbotRoleType } from '@graasp/sdk';
4+
import { Typography } from '@mui/material';
65

76
type ChatbotPromptDisplayProps = {
8-
messages: ChatBotMessage[];
9-
};
10-
11-
const roleColors: Record<ChatbotRoleType, string> = {
12-
[ChatbotRole.System]: '#bdbdbd',
13-
[ChatbotRole.Assistant]: '#1976d2',
14-
[ChatbotRole.User]: '#43a047',
7+
prompt?: string;
158
};
169

17-
const roleLabels: Record<ChatbotRoleType, string> = {
18-
[ChatbotRole.System]: 'System',
19-
[ChatbotRole.Assistant]: 'Assistant',
20-
[ChatbotRole.User]: 'User',
21-
};
10+
export function ChatbotPromptDisplay({
11+
prompt,
12+
}: Readonly<ChatbotPromptDisplayProps>): JSX.Element {
13+
const { t } = useTranslation();
2214

23-
function justifyContentByRole(
24-
role: ChatbotRoleType,
25-
): 'flex-end' | 'flex-start' | 'center' {
26-
if (role === ChatbotRole.User) {
27-
return 'flex-end';
28-
}
29-
if (role === ChatbotRole.Assistant) {
30-
return 'flex-start';
15+
if (!prompt) {
16+
return (
17+
<Typography color="text.disabled" fontStyle="italic">
18+
{t('The prompt is empty.')}
19+
</Typography>
20+
);
3121
}
32-
return 'center';
33-
}
3422

35-
export function ChatbotPromptDisplay({
36-
messages,
37-
}: Readonly<ChatbotPromptDisplayProps>): JSX.Element {
3823
return (
39-
<Stack spacing={2}>
40-
{messages.map((msg, idx) => (
41-
<Box
42-
key={idx}
43-
sx={{
44-
display: 'flex',
45-
flexDirection: 'row',
46-
alignItems: 'flex-end',
47-
justifyContent: justifyContentByRole(msg.role),
48-
}}
49-
>
50-
<Paper
51-
elevation={2}
52-
sx={{
53-
px: 2,
54-
py: 1.5,
55-
maxWidth: '70%',
56-
borderRadius: 3,
57-
backgroundColor: roleColors[msg.role],
58-
color: msg.role === ChatbotRole.System ? '#333' : '#fff',
59-
boxShadow: '0 2px 8px rgba(0,0,0,0.08)',
60-
position: 'relative',
61-
}}
62-
>
63-
<Typography
64-
variant="caption"
65-
sx={{
66-
fontWeight: 700,
67-
opacity: 0.8,
68-
mb: 0.5,
69-
display: 'block',
70-
}}
71-
>
72-
{roleLabels[msg.role]}
73-
</Typography>
74-
<Typography variant="body1" sx={{ whiteSpace: 'pre-line' }}>
75-
{msg.content}
76-
</Typography>
77-
</Paper>
78-
</Box>
79-
))}
80-
</Stack>
24+
<Typography variant="body1" sx={{ whiteSpace: 'pre-line' }}>
25+
{prompt}
26+
</Typography>
8127
);
8228
}

0 commit comments

Comments
 (0)