Skip to content

Commit

Permalink
Add PR #290 (#291)
Browse files Browse the repository at this point in the history
  • Loading branch information
kumaranvpl authored Apr 4, 2024
2 parents 5dc9d2a + e3b36e0 commit 6193e78
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 47 deletions.
10 changes: 10 additions & 0 deletions app/main.wasp
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,16 @@ action updateCurrentConversation {
entities: [Conversation]
}

action deleteLastConversationInChat {
fn: import { deleteLastConversationInChat } from "@src/server/actions.js",
entities: [Conversation]
}

action retryTeamChat {
fn: import { retryTeamChat } from "@src/server/actions.js",
entities: [Chat, Conversation]
}

action createNewAndReturnAllConversations {
fn: import { createNewAndReturnAllConversations } from "@src/server/actions.js",
entities: [Conversation]
Expand Down
17 changes: 10 additions & 7 deletions app/src/client/app/ChatPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ const ChatPage = ({ user }: { user: User }) => {

const handleFormSubmit = async (
userQuery: string,
isUserRespondedWithNextAction: boolean = false
isUserRespondedWithNextAction: boolean = false,
retrySameChat: boolean = false
) => {
if (currentChatDetails.userId !== user.id) {
window.alert('Error: This chat does not belong to you.');
Expand All @@ -82,11 +83,13 @@ const ChatPage = ({ user }: { user: User }) => {
);
const messages: any = await getFormattedChatMessages(
activeChatId,
userQuery
userQuery,
retrySameChat
);
inProgressConversation = await getInProgressConversation(
activeChatId,
userQuery
userQuery,
retrySameChat
);
// if the chat has customerBrief already then directly send required detalils in socket event
if (
Expand Down Expand Up @@ -130,12 +133,12 @@ const ChatPage = ({ user }: { user: User }) => {
});
};

let googleRedirectLoginMsg = queryParams.get('msg');
let triggerChatFormSubmitMsg = queryParams.get('msg');
if (
googleRedirectLoginMsg &&
triggerChatFormSubmitMsg &&
currentChatDetails?.userRespondedWithNextAction
) {
googleRedirectLoginMsg = null;
triggerChatFormSubmitMsg = null;
}

const userSelectedAction: any = queryParams.get('selected_user_action');
Expand All @@ -154,7 +157,7 @@ const ChatPage = ({ user }: { user: User }) => {
<ChatLayout
handleFormSubmit={handleFormSubmit}
currentChatDetails={currentChatDetails}
googleRedirectLoginMsg={googleRedirectLoginMsg}
triggerChatFormSubmitMsg={triggerChatFormSubmitMsg}
>
<div className='flex h-full flex-col'>
{currentChatDetails ? (
Expand Down
6 changes: 3 additions & 3 deletions app/src/client/app/layout/ChatLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ interface Props {
children?: ReactNode;
handleFormSubmit: any;
currentChatDetails?: Chat | null;
googleRedirectLoginMsg?: string | null;
triggerChatFormSubmitMsg?: string | null;
}

const ChatLayout: FC<Props> = ({
children,
handleFormSubmit,
currentChatDetails,
googleRedirectLoginMsg,
triggerChatFormSubmitMsg,
}) => {
const [sidebarOpen, setSidebarOpen] = useState(false);
const { data: user } = useAuth();
Expand Down Expand Up @@ -88,7 +88,7 @@ const ChatLayout: FC<Props> = ({
<ChatForm
handleFormSubmit={handleFormSubmit}
currentChatDetails={currentChatDetails}
googleRedirectLoginMsg={googleRedirectLoginMsg}
triggerChatFormSubmitMsg={triggerChatFormSubmitMsg}
/>
) : (
<></>
Expand Down
12 changes: 6 additions & 6 deletions app/src/client/components/ChatForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,29 @@ import React, { useRef, useState, useEffect, useCallback } from 'react';
interface ChatFormProps {
handleFormSubmit: (userQuery: string) => void;
currentChatDetails: Chat;
googleRedirectLoginMsg?: string | null;
triggerChatFormSubmitMsg?: string | null;
}

export default function ChatForm({
handleFormSubmit,
currentChatDetails,
googleRedirectLoginMsg,
triggerChatFormSubmitMsg,
}: ChatFormProps) {
const [formInputValue, setFormInputValue] = useState('');

const formInputRef = useCallback(
async (node: any) => {
if (node !== null && googleRedirectLoginMsg) {
if (node !== null && triggerChatFormSubmitMsg) {
// @ts-ignore
await handleFormSubmit(googleRedirectLoginMsg, true);
await handleFormSubmit(triggerChatFormSubmitMsg, true);
}
// if (node !== null && userSelectedActionMessage) {
// // @ts-ignore
// await handleFormSubmit(userSelectedActionMessage, true);
// }
},
[googleRedirectLoginMsg]
// [googleRedirectLoginMsg, userSelectedActionMessage]
[triggerChatFormSubmitMsg]
// [triggerChatFormSubmitMsg, userSelectedActionMessage]
);

const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
Expand Down
4 changes: 2 additions & 2 deletions app/src/client/components/ConversationList.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { useSocketListener } from "wasp/client/webSocket";
import { type Conversation, type Chat } from "wasp/entities";
import { useSocketListener } from 'wasp/client/webSocket';
import { type Conversation, type Chat } from 'wasp/entities';

import React from 'react';
import { useState, useEffect } from 'react';
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/components/LoadingComponent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default function LoadingComponent() {
className='inline-flex items-center px-4 py-2 leading-6 text-sm shadow rounded-md transition ease-in-out duration-150 cursor-not-allowed border border-captn-dark-blue'
disabled
>
<MessageIcon /> Please wait a moment while we log you in.
<MessageIcon /> Loading...
</button>
</div>
</div>
Expand Down
17 changes: 12 additions & 5 deletions app/src/client/components/SmartSuggestionButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type Chat } from 'wasp/entities';
import {
createNewChat,
retryTeamChat,
createNewDailyAnalysisChat,
} from 'wasp/client/operations';
import React, { useState } from 'react';
Expand All @@ -25,12 +25,19 @@ export default function SmartSuggestionButton({
) {
if (currentChatDetails.isExceptionOccured) {
if (currentChatDetails.chatType === 'daily_analysis') {
const newChat: Chat =
const [newChat, lastConversationMessage] =
await createNewDailyAnalysisChat(currentChatDetails);
history.push(`/chat/${newChat.uuid}`);
history.push(`/chat/${newChat.uuid}?msg=${lastConversationMessage}`);
} else {
const chat: Chat = await createNewChat();
history.push(`/chat/${chat.uuid}`);
if (currentChatDetails.team_name) {
const [chat, lastConversationMessage] = await retryTeamChat(
currentChatDetails.id
);
history.push(`/chat/${chat.uuid}?msg=${lastConversationMessage}`);
} else {
setIsShowSuggestions(false);
smartSuggestionOnClick(null, false, true);
}
}
} else {
smartSuggestionOnClick(suggestion);
Expand Down
2 changes: 1 addition & 1 deletion app/src/client/tests/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import App from '../App';
test('renders App component', async () => {
renderInContext(<App children={<div>Test</div>} />);

await screen.findByText('Please wait a moment while we log you in.');
await screen.findByText('Loading...');

screen.debug();
});
137 changes: 137 additions & 0 deletions app/src/client/tests/SmartSuggestionButton.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { test, expect, vi, describe } from 'vitest';
import { renderInContext } from 'wasp/client/test';
import { fireEvent, screen, waitFor } from '@testing-library/react';
import * as operations from 'wasp/client/operations';
import { createMemoryHistory } from 'history';

import { type Chat } from 'wasp/entities';
import SmartSuggestionButton from '../components/SmartSuggestionButton';

vi.mock('wasp/client/operations', async (importOriginal) => {
const mod = await importOriginal<typeof import('wasp/client/operations')>();
return {
...mod,
createNewDailyAnalysisChat: vi
.fn()
.mockResolvedValue([{ uuid: '123' }, 'Sample user message']),
retryTeamChat: vi
.fn()
.mockResolvedValue([{ uuid: '123' }, 'Sample user message']),
};
});

describe('SmartSuggestionButton', () => {
test('renders the correct suggestions', () => {
const mockOnClick = vi.fn();
const currentChatDetails: Partial<Chat> = {
smartSuggestions: {
suggestions: ['Suggestion 1', 'Suggestion 2'],
},
isExceptionOccured: false,
};

renderInContext(
<SmartSuggestionButton
// @ts-ignore
currentChatDetails={currentChatDetails}
smartSuggestionOnClick={mockOnClick}
/>
);
});

test('handles suggestion click correctly', () => {
const mockOnClick = vi.fn();
const currentChatDetails: Partial<Chat> = {
smartSuggestions: {
suggestions: ['Suggestion 1', 'Suggestion 2'],
},
isExceptionOccured: false,
};

renderInContext(
<SmartSuggestionButton
// @ts-ignore
currentChatDetails={currentChatDetails}
smartSuggestionOnClick={mockOnClick}
/>
);

fireEvent.click(screen.getByText('Suggestion 1'));
expect(mockOnClick).toHaveBeenCalledWith('Suggestion 1');
});

test('handles exception correctly', () => {
const mockOnClick = vi.fn();
const currentChatDetails: Partial<Chat> = {
smartSuggestions: {
suggestions: ['Suggestion 1', 'Suggestion 2'],
},
isExceptionOccured: true,
chatType: 'normal_chat',
};

renderInContext(
<SmartSuggestionButton
// @ts-ignore
currentChatDetails={currentChatDetails}
smartSuggestionOnClick={mockOnClick}
/>
);

fireEvent.click(screen.getByText('Suggestion 1'));
expect(mockOnClick).toHaveBeenCalledWith(null, false, true);
});

test('handles daily_analysis chat type correctly', async () => {
const mockOnClick = vi.fn();
const currentChatDetails: Partial<Chat> = {
chatType: 'daily_analysis',
smartSuggestions: {
suggestions: ['Suggestion 1', 'Suggestion 2'],
},
isExceptionOccured: true,
};

renderInContext(
<SmartSuggestionButton
// @ts-ignore
currentChatDetails={currentChatDetails}
smartSuggestionOnClick={mockOnClick}
/>
);

fireEvent.click(screen.getByText('Suggestion 1'));

expect(operations.createNewDailyAnalysisChat).toHaveBeenCalledWith(
currentChatDetails
);
});

test('handles team chat type correctly', async () => {
const mockOnClick = vi.fn();
const history = createMemoryHistory();
const currentChatDetails: Partial<Chat> = {
chatType: 'normal_chat',
team_name: 'Team Name',
smartSuggestions: {
suggestions: ['Suggestion 1', 'Suggestion 2'],
},
isExceptionOccured: true,
id: 1,
};

renderInContext(
<SmartSuggestionButton
// @ts-ignore
currentChatDetails={currentChatDetails}
smartSuggestionOnClick={mockOnClick}
/>
);

fireEvent.click(screen.getByText('Suggestion 1'));

expect(operations.retryTeamChat).toHaveBeenCalledWith(
currentChatDetails.id
);
});
});
Loading

0 comments on commit 6193e78

Please sign in to comment.