- Builder as {permission}
-
-
-
-
-
-
-
-
-
- App Data
- {JSON.stringify(appDatas, null, 2)}
-
-
-
-
+
+
+
+
+ setActiveTab(newTab)} // Update the active tab when a new tab is selected
+ centered
+ >
+ }
+ iconPosition="start"
+ />
+ }
+ iconPosition="start"
+ />
+ }
+ iconPosition="start"
+ />
+
+ setActiveTab(newTab)} // Update the active tab when a new tab is selected
+ centered
+ >
+ }
+ iconPosition="start"
+ />
+
+
+
+
+
+
+ }
+ variant="contained"
+ onClick={() => saveSettings('assistants', assistants)}
+ disabled={useMemo(
+ () =>
+ // Disable if settings have not changed or list is empty
+ isEqual(assistantsSavedState, assistants) ||
+ assistants.assistantList.length === 0,
+ [assistants, assistantsSavedState],
+ )}
+ >
+ {t('SETTINGS.SAVE_BTN')}
+
+
+
+
+
+
+
+
+ }
+ variant="contained"
+ onClick={() => saveSettings('chat', chat)}
+ disabled={useMemo(
+ // Disable if settings have not changed
+ () => isEqual(chatSavedState, chat),
+ [chat, chatSavedState],
+ )}
+ >
+ {t('SETTINGS.SAVE_BTN')}
+
+
+
+
+
+
+
+
+ }
+ variant="contained"
+ onClick={() => saveSettings('exchanges', exchanges)}
+ disabled={useMemo(
+ () =>
+ // Disable if settings have not changed or list is empty
+ isEqual(exchangesSavedState, exchanges) ||
+ exchanges.exchangeList.length === 0,
+ [exchanges, exchangesSavedState],
+ )}
+ >
+ {t('SETTINGS.SAVE_BTN')}
+
+
+
+
+
+
+
+
+
);
};
diff --git a/src/modules/main/PlayerView.tsx b/src/modules/main/PlayerView.tsx
index 5bcc98f..78c4eed 100644
--- a/src/modules/main/PlayerView.tsx
+++ b/src/modules/main/PlayerView.tsx
@@ -1,22 +1,10 @@
-// import { Typography } from '@mui/material';
-// import { useLocalContext } from '@graasp/apps-query-client';
-// import { hooks } from '@/config/queryClient';
import { Box } from '@mui/material';
import { PLAYER_VIEW_CY } from '@/config/selectors';
import ParticipantInteraction from '@/modules/interaction/ParticipantInteraction';
const PlayerView = (): JSX.Element => (
- // const { permission } = useLocalContext();
- // const { data: appContext } = hooks.useAppContext();
- // const members = appContext?.members;
-
- {/* Player as {permission} */}
- {/* */}
- {/* Members */}
- {/* {JSON.stringify(members, null, 2)}
*/}
- {/* */}
);
diff --git a/src/modules/message/MessageInput.tsx b/src/modules/message/MessageInput.tsx
index cf1a45e..a1bc843 100644
--- a/src/modules/message/MessageInput.tsx
+++ b/src/modules/message/MessageInput.tsx
@@ -1,4 +1,5 @@
import { ReactElement, useEffect, useRef, useState } from 'react';
+import { useTranslation } from 'react-i18next';
import CheckIcon from '@mui/icons-material/CheckRounded';
import SendRoundedIcon from '@mui/icons-material/SendRounded';
@@ -8,50 +9,36 @@ import FormControl from '@mui/material/FormControl';
import Textarea from '@mui/material/OutlinedInput';
import Stack from '@mui/material/Stack';
-import Exchange from '@/types/Exchange';
-
export type MessageInputProps = {
- exchange: Exchange;
- textAreaValue: string;
- setTextAreaValue: (value: string) => void;
- onSubmit: (keyPressData: KeyPressData[]) => void;
- completed: boolean;
- setExchange: (exchange: Exchange) => void;
- goToNextExchange: () => void;
-};
-
-type KeyPressData = {
- timestamp: number;
- key: string;
+ dismissExchange: () => void;
+ onSubmit: ({ content }: { content: string }) => void;
+ exchangeCompleted: boolean;
};
+// Main component function: MessageInput
const MessageInput = ({
- exchange,
- textAreaValue,
- setTextAreaValue,
+ dismissExchange,
onSubmit,
- completed,
- setExchange,
- goToNextExchange,
+ exchangeCompleted,
}: MessageInputProps): ReactElement => {
+ // State to manage the value of the textarea input
+ const [textAreaValue, setTextAreaValue] = useState('');
+
+ // Ref to get direct access to the textarea DOM element
const textAreaRef = useRef
(null);
- const [keypressData, setKeypressData] = useState([]);
- function dismissExchange(): void {
- const updatedExchange = { ...exchange };
- updatedExchange.dismissed = true;
- updatedExchange.dismissedAt = new Date();
- setExchange(updatedExchange);
- goToNextExchange();
- }
+ // Hook for internationalization (i18n) translation
+ const { t } = useTranslation();
- // const focusOnTextArea = (): void => {
- // const textareaElement = textAreaRef?.current?.querySelector('textarea');
- // if (textareaElement) {
- // textareaElement.focus();
- // }
- // };
+ // Function to focus on the textarea input
+ const focusOnTextArea = (): void => {
+ const textareaElement = textAreaRef?.current?.querySelector('textarea');
+ if (textareaElement) {
+ textareaElement.focus();
+ }
+ };
+ // Function to remove focus from the textarea input
const blurTextArea = (): void => {
const textareaElement = textAreaRef?.current?.querySelector('textarea');
if (textareaElement) {
@@ -59,22 +46,24 @@ const MessageInput = ({
}
};
+ // Effect to focus on the textarea whenever the component renders
useEffect(() => {
- // focusOnTextArea();
+ focusOnTextArea();
});
+ // Function to handle the send button click
const handleClick = (): void => {
if (textAreaValue.trim() !== '') {
- onSubmit(keypressData);
+ onSubmit({ content: textAreaValue });
+
setTextAreaValue('');
- // focus on the text area
- // focusOnTextArea();
- // blue text area
+ focusOnTextArea();
blurTextArea();
}
};
+ // Function to handle the dismiss button click
const handleDismiss = (): void => {
dismissExchange();
};
@@ -83,7 +72,7 @@ const MessageInput = ({
- {!(readOnly || exchange.dismissed) && (
+ {!currentExchange.dismissed && !readOnly && (
{
- saveNewMessage({
- // keyPressEvents,
- // sender: participantId,
- content: textAreaValue,
- });
- }}
+ dismissExchange={() => dismissExchange()}
+ onSubmit={saveNewMessage}
+ exchangeCompleted={currentExchange.completed}
/>
)}
diff --git a/src/results/ConversationsView.tsx b/src/results/ConversationsView.tsx
new file mode 100644
index 0000000..13256a4
--- /dev/null
+++ b/src/results/ConversationsView.tsx
@@ -0,0 +1,160 @@
+import { FC, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import DeleteIcon from '@mui/icons-material/Delete';
+import {
+ Alert,
+ Box,
+ FormControl,
+ IconButton,
+ InputLabel,
+ MenuItem,
+ Select,
+ Tooltip,
+ Typography,
+} from '@mui/material';
+import Stack from '@mui/material/Stack';
+
+import { Member } from '@graasp/sdk';
+
+import { hooks, mutations } from '@/config/queryClient';
+import MessagesPane from '@/modules/message/MessagesPane';
+import Interaction from '@/types/Interaction';
+
+type Props = {
+ checkedOutMember: Member;
+ setCheckedOutMember: (newCheckedOutMember: Member) => void;
+};
+
+// Main component for managing conversations
+const Conversations: FC = ({
+ checkedOutMember,
+ setCheckedOutMember,
+}) => {
+ const { t } = useTranslation();
+
+ // Hook to handle deleting app data
+ const { mutate: deleteAppData } = mutations.useDeleteAppData();
+
+ // Fetching interaction data
+ const { data: appDatas } = hooks.useAppData();
+
+ // Fetching all members from the app context or defaulting to the checked-out member
+ const allMembers = hooks.useAppContext().data?.members || [checkedOutMember];
+
+ // Memoized value to find the interaction corresponding to the selected member
+ const checkedOutInteraction = useMemo(
+ () =>
+ appDatas?.find(
+ (appData) =>
+ appData?.data?.exchanges?.exchangeList &&
+ appData.member.id === checkedOutMember.id,
+ )?.data,
+ [appDatas, checkedOutMember.id],
+ );
+
+ return (
+
+ {t('CONVERSATIONS.TITLE')}
+
+
+ {t('CONVERSATIONS.MEMBER')}
+
+
+
+ {checkedOutMember.id === '' ? null : (
+
+ {checkedOutInteraction ? (
+
+ {}}
+ interactionDescription=""
+ pastMessages={
+ checkedOutInteraction.exchanges.exchangeList.flatMap(
+ (exchange) => {
+ // Collect dismissed messages from exchanges
+ if (exchange.dismissed) {
+ return exchange.messages;
+ }
+ return [];
+ },
+ ) || []
+ }
+ participant={checkedOutInteraction.participant}
+ autoDismiss={false}
+ goToNextExchange={() => {}}
+ readOnly
+ />
+ {checkedOutInteraction.completed ? (
+
+ {t('CONVERSATIONS.COMPLETE')}
+
+ ) : (
+
+ {t('CONVERSATIONS.INCOMPLETE')}
+
+ )}
+
+
+
+ deleteAppData({
+ id:
+ appDatas?.find(
+ (appData) =>
+ appData.member.id === checkedOutMember.id,
+ )?.id || '',
+ })
+ }
+ sx={{ width: 'auto' }}
+ >
+
+
+
+
+
+
+ ) : (
+ // Show a warning if no interaction is found
+
+ {t('CONVERSATIONS.NONE')}
+
+ )}
+
+ )}
+
+ );
+};
+
+export default Conversations;
diff --git a/src/settings/AssistantSettings.tsx b/src/settings/AssistantSettings.tsx
new file mode 100644
index 0000000..738abd1
--- /dev/null
+++ b/src/settings/AssistantSettings.tsx
@@ -0,0 +1,266 @@
+import { FC, SetStateAction } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
+import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
+import DeleteIcon from '@mui/icons-material/Delete';
+import {
+ Alert,
+ Avatar,
+ Box,
+ Button,
+ Divider,
+ IconButton,
+ Tooltip,
+} from '@mui/material';
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+import Typography from '@mui/material/Typography';
+
+import { v4 as uuidv4 } from 'uuid';
+
+import { AssistantsSettingsType } from '@/config/appSettings';
+import { MAX_TEXT_INPUT_CHARS } from '@/config/config';
+import Agent from '@/types/Agent';
+import AgentType from '@/types/AgentType';
+
+// Prop types for individual assistant settings panel
+type PropTypesSingle = {
+ assistant: AssistantsSettingsType['assistantList'][number];
+ onChange: (
+ index: number,
+ field: keyof AssistantsSettingsType['assistantList'][number],
+ value: string,
+ ) => void;
+ handleRemoveAssistant: (index: number) => void;
+ handleMoveUp: (index: number) => void;
+ handleMoveDown: (index: number) => void;
+ index: number;
+ assistantListLength: number;
+};
+
+// Component for individual assistant settings panel
+const AssistantSettingsPanel: FC = ({
+ assistant,
+ onChange,
+ handleRemoveAssistant,
+ handleMoveUp,
+ handleMoveDown,
+ index,
+ assistantListLength,
+}) => {
+ const { t } = useTranslation();
+
+ // Destructuring assistant properties
+ const {
+ name: assistantName,
+ description: assistantDescription,
+ imageUrl: assistantImageUrl,
+ } = assistant;
+
+ // Generating a unique color for the assistant panel based on its ID
+ const panelColor: string = `#0${assistant.id.slice(0, 5)}`;
+
+ return (
+
+ }
+ >
+
+ {index + 1}
+
+
+
+
+
+ {assistantName.slice(0, 2)}
+
+ onChange(index, 'imageUrl', e.target.value)}
+ placeholder={t('SETTINGS.ASSISTANTS.URL')}
+ fullWidth
+ />
+ handleMoveUp(index)}
+ disabled={index === 0} // Disabled if the assistant is at the top
+ >
+
+
+
+
+ handleMoveDown(index)}
+ disabled={index === assistantListLength - 1} // Disabled if the assistant is at the bottom
+ >
+
+
+
+
+
+ onChange(index, 'name', e.target.value)}
+ />
+ onChange(index, 'description', e.target.value)}
+ />
+
+ handleRemoveAssistant(index)}
+ sx={{ width: 'auto' }}
+ >
+
+
+
+
+
+
+ );
+};
+
+// Prop types for the main assistants settings component
+type PropTypeList = {
+ assistants: AssistantsSettingsType;
+ onChange: (value: SetStateAction) => void;
+};
+
+// Main component for managing assistants settings
+const AssistantsSettings: FC = ({ assistants, onChange }) => {
+ const { t } = useTranslation();
+
+ // Function to add a new assistant to the list
+ const handleAddAssistant = (): void => {
+ onChange((prev) => ({
+ assistantList: [
+ // Spreading existing assistants
+ ...prev.assistantList,
+ {
+ // Generating a unique ID for the new assistant
+ id: uuidv4(),
+ name: '',
+ description: '',
+ imageUrl: '',
+ },
+ ],
+ }));
+ };
+
+ // Function to remove an assistant from the list
+ const handleRemoveAssistant = (index: number): void => {
+ onChange((prev) => ({
+ // Removing the assistant at the specified index
+ assistantList: prev.assistantList.filter((_, i) => i !== index),
+ }));
+ };
+
+ // Function to move an assistant up in the list
+ const handleMoveUp = (index: number): void => {
+ onChange((prev) => {
+ const updatedAssistants = [...prev.assistantList];
+ const [movedAssistant] = updatedAssistants.splice(index, 1);
+ updatedAssistants.splice(index - 1, 0, movedAssistant);
+ return { assistantList: updatedAssistants };
+ });
+ };
+
+ // Function to move an assistant down in the list
+ const handleMoveDown = (index: number): void => {
+ onChange((prev) => {
+ const updatedAssistants = [...prev.assistantList];
+ const [movedAssistant] = updatedAssistants.splice(index, 1);
+ updatedAssistants.splice(index + 1, 0, movedAssistant);
+ return { assistantList: updatedAssistants };
+ });
+ };
+
+ // Function to handle changes in the assistant's fields (name, description, image URL)
+ const handleChange = (
+ index: number,
+ field: keyof AssistantsSettingsType['assistantList'][number],
+ value: string | number | boolean | (Agent & { type: AgentType.Assistant }),
+ ): void => {
+ const updatedAssistants = assistants.assistantList.map((assistant, i) =>
+ // Updating the specified field of the assistant at the specified index
+ i === index ? { ...assistant, [field]: value } : assistant,
+ );
+
+ // Updating the state with the new list
+ onChange({ assistantList: updatedAssistants });
+ };
+
+ return (
+
+ {t('SETTINGS.ASSISTANTS.TITLE')}
+
+ {assistants.assistantList.length === 0 ? (
+
+ {t('SETTINGS.ASSISTANTS.CREATE')}
+
+ ) : (
+ // Mapping over the list of assistants and rendering a settings panel for each
+ assistants.assistantList.map((assistant, index) => (
+
+ ))
+ )}
+
+
+
+ );
+};
+
+// Exporting the component as the default export
+export default AssistantsSettings;
diff --git a/src/settings/ChatSettings.tsx b/src/settings/ChatSettings.tsx
new file mode 100644
index 0000000..5d7477d
--- /dev/null
+++ b/src/settings/ChatSettings.tsx
@@ -0,0 +1,61 @@
+import { FC } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Typography } from '@mui/material';
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+
+import { ChatSettingsType } from '@/config/appSettings';
+import { MAX_TEXT_INPUT_CHARS } from '@/config/config';
+
+// Prop types for ChatSettings component
+type PropTypes = {
+ chat: ChatSettingsType;
+ onChange: (newSetting: ChatSettingsType) => void;
+};
+
+// ChatSettings component to display and update chat settings
+const ChatSettings: FC = ({ chat, onChange }) => {
+ const { t } = useTranslation();
+
+ // Destructuring chat settings
+ const {
+ description: chatDescription,
+ participantInstructions: chatInstructions,
+ participantEndText: chatEndText,
+ } = chat;
+
+ return (
+
+ {t('SETTINGS.CHAT.TITLE')}
+ onChange({ ...chat, description: e.target.value })}
+ />
+
+ onChange({ ...chat, participantInstructions: e.target.value })
+ }
+ />
+
+ onChange({ ...chat, participantEndText: e.target.value })
+ }
+ />
+
+ );
+};
+
+// Exporting the component as the default export
+export default ChatSettings;
diff --git a/src/settings/ExchangesSettings.tsx b/src/settings/ExchangesSettings.tsx
new file mode 100644
index 0000000..48ad90e
--- /dev/null
+++ b/src/settings/ExchangesSettings.tsx
@@ -0,0 +1,376 @@
+import { FC, SetStateAction } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import ArrowDownwardIcon from '@mui/icons-material/ArrowDownward';
+import ArrowUpwardIcon from '@mui/icons-material/ArrowUpward';
+import DeleteIcon from '@mui/icons-material/Delete';
+import InfoBadge from '@mui/icons-material/Info';
+import {
+ Alert,
+ Avatar,
+ Box,
+ Button,
+ Divider,
+ FormControl,
+ IconButton,
+ InputLabel,
+ MenuItem,
+ Select,
+ Switch,
+ Tooltip,
+} from '@mui/material';
+import Stack from '@mui/material/Stack';
+import TextField from '@mui/material/TextField';
+import Typography from '@mui/material/Typography';
+
+import { v4 as uuidv4 } from 'uuid';
+
+import { ExchangesSettingsType } from '@/config/appSettings';
+import {
+ MAX_FOLLOW_UP_QUESTIONS,
+ MAX_TEXT_INPUT_CHARS,
+ MIN_FOLLOW_UP_QUESTIONS,
+} from '@/config/config';
+import { useSettings } from '@/modules/context/SettingsContext';
+import Agent from '@/types/Agent';
+
+// Prop types for ExchangeSettingsPanel component
+type PropTypesSingle = {
+ exchange: ExchangesSettingsType['exchangeList'][number];
+ onChange: (
+ index: number,
+ field: keyof ExchangesSettingsType['exchangeList'][number],
+ // Value type to update
+ value: string | number | boolean | Omit,
+ ) => void;
+ handleRemoveExchange: (index: number) => void;
+ handleMoveUp: (index: number) => void;
+ handleMoveDown: (index: number) => void;
+ index: number;
+ exchangeListLength: number;
+};
+
+// ExchangeSettingsPanel component to display and edit individual exchange settings
+const ExchangeSettingsPanel: FC = ({
+ exchange,
+ onChange,
+ handleRemoveExchange,
+ handleMoveUp,
+ handleMoveDown,
+ index,
+ exchangeListLength,
+}) => {
+ const { t } = useTranslation();
+
+ // Destructuring exchange settings
+ const {
+ assistant: exchangeAssistant,
+ description: exchangeDescription,
+ chatbotInstructions: exchangeInstructions,
+ participantCue: exchangeCue,
+ participantInstructionsOnComplete: exchangeOnComplete,
+ nbFollowUpQuestions: exchangeFollowUpQuestions,
+ hardLimit: exchangeLimit,
+ } = exchange;
+
+ // Color based on exchange ID
+ const panelColor: string = `#0${exchange.id.slice(0, 5)}`;
+
+ // Getting assistants from settings context
+ const { assistants } = useSettings();
+
+ return (
+
+ }
+ >
+
+ {index + 1}
+
+
+
+
+ onChange(index, 'description', e.target.value)}
+ />
+ handleMoveUp(index)}
+ disabled={index === 0} // Disable if already at the top
+ >
+
+
+
+
+ handleMoveDown(index)}
+ disabled={index === exchangeListLength - 1} // Disable if already at the bottom
+ >
+
+
+
+
+
+
+ onChange(index, 'chatbotInstructions', e.target.value)
+ }
+ />
+ onChange(index, 'participantCue', e.target.value)}
+ />
+
+
+ {exchangeAssistant.name.slice(0, 2)}
+
+
+ {t('SETTINGS.EXCHANGES.ASSISTANT')}
+
+
+
+
+ onChange(
+ index,
+ 'nbFollowUpQuestions',
+ parseInt(e.target.value, 10),
+ )
+ }
+ />
+
+ {t('SETTINGS.EXCHANGES.DISABLE_HARD_LIMIT')}
+ {' '}
+
+
+
+
+ onChange(index, 'hardLimit', e.target.checked)}
+ />
+ {!exchangeLimit && (
+
+ onChange(
+ index,
+ 'participantInstructionsOnComplete',
+ e.target.value,
+ )
+ }
+ />
+ )}
+
+ {
+ handleRemoveExchange(index);
+ }}
+ sx={{ alignSelf: 'center', width: 'auto' }}
+ >
+
+
+
+
+
+
+ );
+};
+
+// Prop types for ExchangeSettings component
+type PropTypeList = {
+ exchanges: ExchangesSettingsType;
+ onChange: (value: SetStateAction) => void;
+};
+
+// ExchangeSettings component to manage a list of exchanges
+const ExchangeSettings: FC = ({ exchanges, onChange }) => {
+ // Translation hook
+ const { t } = useTranslation();
+
+ // Add a new exchange to the list
+ const handleAddExchange = (): void => {
+ onChange((prev) => ({
+ exchangeList: [
+ ...prev.exchangeList,
+ {
+ // Generate a new unique ID
+ id: uuidv4(),
+ assistant: {
+ id: '',
+ name: '',
+ description: '',
+ },
+ description: '',
+ chatbotInstructions: '',
+ participantCue: '',
+ participantInstructionsOnComplete: '',
+ nbFollowUpQuestions: 0,
+ hardLimit: false,
+ },
+ ],
+ }));
+ };
+
+ // Remove an exchange from the list
+ const handleRemoveExchange = (index: number): void => {
+ onChange((prev) => ({
+ exchangeList: prev.exchangeList.filter((_, i) => i !== index),
+ }));
+ };
+
+ // Move an exchange up in the list
+ const handleMoveUp = (index: number): void => {
+ onChange((prev) => {
+ const updatedExchanges = [...prev.exchangeList];
+ const [movedExchange] = updatedExchanges.splice(index, 1);
+ updatedExchanges.splice(index - 1, 0, movedExchange);
+ return { exchangeList: updatedExchanges };
+ });
+ };
+
+ // Move an exchange down in the list
+ const handleMoveDown = (index: number): void => {
+ onChange((prev) => {
+ const updatedExchanges = [...prev.exchangeList];
+ const [movedExchange] = updatedExchanges.splice(index, 1);
+ updatedExchanges.splice(index + 1, 0, movedExchange);
+ return { exchangeList: updatedExchanges };
+ });
+ };
+
+ // Handle changes to exchange settings
+ const handleChange = (
+ index: number,
+ field: keyof ExchangesSettingsType['exchangeList'][number],
+ value: string | number | boolean | Omit,
+ ): void => {
+ const updatedExchanges = exchanges.exchangeList.map((exchange, i) =>
+ i === index ? { ...exchange, [field]: value } : exchange,
+ );
+
+ onChange({ exchangeList: updatedExchanges });
+ };
+
+ return (
+
+ {t('SETTINGS.EXCHANGES.TITLE')}
+
+ {exchanges.exchangeList.length === 0 ? (
+
+ {t('SETTINGS.EXCHANGES.CREATE')}
+
+ ) : (
+ exchanges.exchangeList.map((exchange, index) => (
+
+ ))
+ )}
+
+
+
+ );
+};
+
+// Exporting the component as the default export
+export default ExchangeSettings;
diff --git a/src/types/Agent.ts b/src/types/Agent.ts
index b4d4602..8ac0f7a 100644
--- a/src/types/Agent.ts
+++ b/src/types/Agent.ts
@@ -1,10 +1,13 @@
+import { UUID } from '@graasp/sdk';
+
import AgentType from '@/types/AgentType';
type Agent = {
- id: string;
+ id: UUID;
type: AgentType;
description?: string;
name: string;
+ imageUrl?: string;
};
export default Agent;
diff --git a/src/types/Exchange.ts b/src/types/Exchange.ts
index 8012dc0..ff6422f 100644
--- a/src/types/Exchange.ts
+++ b/src/types/Exchange.ts
@@ -1,23 +1,14 @@
+import { ExchangeSettings } from '@/config/appSettings';
+
import Agent from './Agent';
import { Message } from './Message';
-import Trigger from './Trigger';
-type Exchange = {
- id: number;
- name: string;
- description: string;
- instructions: string;
- participantInstructionsOnComplete: string;
- cue: string;
- order: number;
- messages: Message[];
+type Exchange = ExchangeSettings & {
assistant: Agent;
- triggers: Trigger[];
+ messages: Message[];
started: boolean;
completed: boolean;
dismissed: boolean;
- softLimit: number;
- hardLimit: number;
startedAt?: Date;
completedAt?: Date;
dismissedAt?: Date;
diff --git a/src/types/Interaction.ts b/src/types/Interaction.ts
index 5756ca3..4010278 100644
--- a/src/types/Interaction.ts
+++ b/src/types/Interaction.ts
@@ -1,18 +1,17 @@
+import { UUID } from '@graasp/sdk';
+
+import { ChatSettingsType } from '@/config/appSettings';
+
import Agent from './Agent';
import Exchange from './Exchange';
-type Interaction = {
- id: number;
- description: string;
- modelInstructions: string;
- participantInstructions: string;
- participantInstructionsOnComplete: string;
- name: string;
+type Interaction = ChatSettingsType & {
+ id: UUID;
currentExchange: number;
completed: boolean;
started: boolean;
participant: Agent;
- exchanges: Exchange[];
+ exchanges: { exchangeList: Exchange[] };
startedAt?: Date;
completedAt?: Date;
createdAt: Date;
diff --git a/yarn.lock b/yarn.lock
index 93b4b63..3e7f1e4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5165,9 +5165,9 @@ __metadata:
linkType: hard
"async@npm:^3.2.0":
- version: 3.2.5
- resolution: "async@npm:3.2.5"
- checksum: 10/323c3615c3f0ab1ac25a6f953296bc0ac3213d5e0f1c0debdb12964e55963af288d570293c11e44f7967af58c06d2a88d0ea588c86ec0fbf62fa98037f604a0f
+ version: 3.2.6
+ resolution: "async@npm:3.2.6"
+ checksum: 10/cb6e0561a3c01c4b56a799cc8bab6ea5fef45f069ab32500b6e19508db270ef2dffa55e5aed5865c5526e9907b1f8be61b27530823b411ffafb5e1538c86c368
languageName: node
linkType: hard
@@ -6009,11 +6009,11 @@ __metadata:
linkType: hard
"core-js-compat@npm:^3.37.1, core-js-compat@npm:^3.38.0":
- version: 3.38.0
- resolution: "core-js-compat@npm:3.38.0"
+ version: 3.38.1
+ resolution: "core-js-compat@npm:3.38.1"
dependencies:
browserslist: "npm:^4.23.3"
- checksum: 10/7ebdca6b305c9c470980e1f7e7a3d759add7cb754bff62926242907ee4d1d4e8bb13f70eb9a7d7769e0f63aec3f4cca83abf60f502286853b45d4b63a01c25ed
+ checksum: 10/4e2f219354fd268895f79486461a12df96f24ed307321482fe2a43529c5a64e7c16bcba654980ba217d603444f5141d43a79058aeac77511085f065c5da72207
languageName: node
linkType: hard
@@ -6495,9 +6495,9 @@ __metadata:
linkType: hard
"electron-to-chromium@npm:^1.5.4":
- version: 1.5.11
- resolution: "electron-to-chromium@npm:1.5.11"
- checksum: 10/4342e1a32eba710a6327fa19dd012e2a7c3133151c646d80dec9fba8e3e0dcc1d19438ae561c10d86243f1bae7dc71a01d9dfd36e07e30836e45b214cbd07a25
+ version: 1.5.12
+ resolution: "electron-to-chromium@npm:1.5.12"
+ checksum: 10/6e5ec71e211de06f15147f42eaf8e71bc4dd73da29ce6611046a57614b7d220ffd8671b4fb424161f278498bb47880fccf7648ccbfb8b019e34d38db43520cea
languageName: node
linkType: hard
@@ -11689,7 +11689,7 @@ __metadata:
languageName: node
linkType: hard
-"rollup@npm:^4.13.0":
+"rollup@npm:^4.13.0, rollup@npm:^4.20.0":
version: 4.21.0
resolution: "rollup@npm:4.21.0"
dependencies:
@@ -12848,9 +12848,9 @@ __metadata:
linkType: hard
"undici-types@npm:~6.19.2":
- version: 6.19.6
- resolution: "undici-types@npm:6.19.6"
- checksum: 10/0ea9bc25762a86597d095b3772f6cec0bcabb796c339f7dfa2bd601c745a480289eb2939848dc285a56d4f94f50c475868160d8d6d3f54e823f1faf7ea9e9468
+ version: 6.19.8
+ resolution: "undici-types@npm:6.19.8"
+ checksum: 10/cf0b48ed4fc99baf56584afa91aaffa5010c268b8842f62e02f752df209e3dea138b372a60a963b3b2576ed932f32329ce7ddb9cb5f27a6c83040d8cd74b7a70
languageName: node
linkType: hard
@@ -13184,13 +13184,13 @@ __metadata:
linkType: hard
"vite@npm:^5.0.0":
- version: 5.4.1
- resolution: "vite@npm:5.4.1"
+ version: 5.4.2
+ resolution: "vite@npm:5.4.2"
dependencies:
esbuild: "npm:^0.21.3"
fsevents: "npm:~2.3.3"
postcss: "npm:^8.4.41"
- rollup: "npm:^4.13.0"
+ rollup: "npm:^4.20.0"
peerDependencies:
"@types/node": ^18.0.0 || >=20.0.0
less: "*"
@@ -13222,7 +13222,7 @@ __metadata:
optional: true
bin:
vite: bin/vite.js
- checksum: 10/1cf22e5a8ec782ea9417a77ad4b16e518f69cf23c99a5af5bb92dc4acbfce70109a35a35faea8fc0789f4637b6304618f6b84e4c5dfe3c9c2875dff7d749b02d
+ checksum: 10/c449f9295060fa88c9b5cc1bd17c2de198deae596b7da1250db9662fb15e7b21e0dbe9a40a9106fb7438b1231494b169457e809ecbb65e732648d87dd284ab23
languageName: node
linkType: hard