From 5b9b82012a55918702b5075b664ad26d350aac4a Mon Sep 17 00:00:00 2001 From: Teresa Hoang <125500434+teresaqhoang@users.noreply.github.com> Date: Fri, 12 May 2023 18:38:17 -0700 Subject: [PATCH] Fixing Copilot Chat UI bugs (#981) ### Motivation and Context This PR contains CSS clean-up and fixes for a number of UI bugs. Changes include: - ChatWindow no longer overflows out of window view - Scrollbars show up as necessary in ChatHistory and ChatList ![image](https://github.com/microsoft/semantic-kernel/assets/125500434/d87f4f7f-f01d-49c1-ace6-bcc11ed3984d) - Check for valid .env file on start, error screen showed if variables aren't populated. - --- .../apps/copilot-chat-app/webapp/env.example | 4 +- .../apps/copilot-chat-app/webapp/src/App.tsx | 68 ++++++------ .../copilot-chat-app/webapp/src/checkEnv.ts | 14 +++ .../src/components/chat/ChatHistory.tsx | 3 +- .../webapp/src/components/chat/ChatInput.tsx | 26 +++-- .../webapp/src/components/chat/ChatRoom.tsx | 23 ++-- .../webapp/src/components/chat/ChatWindow.tsx | 94 ++++++---------- .../components/chat/chat-list/ChatList.tsx | 102 +++++++++--------- .../webapp/src/components/views/ChatView.tsx | 7 +- .../views/MissingEnvVariablesError.tsx | 30 ++++++ .../copilot-chat-app/webapp/src/index.tsx | 35 ++++-- 11 files changed, 216 insertions(+), 190 deletions(-) create mode 100644 samples/apps/copilot-chat-app/webapp/src/checkEnv.ts create mode 100644 samples/apps/copilot-chat-app/webapp/src/components/views/MissingEnvVariablesError.tsx diff --git a/samples/apps/copilot-chat-app/webapp/env.example b/samples/apps/copilot-chat-app/webapp/env.example index 2795ae07b9bd..46044e088f97 100644 --- a/samples/apps/copilot-chat-app/webapp/env.example +++ b/samples/apps/copilot-chat-app/webapp/env.example @@ -1,3 +1,5 @@ REACT_APP_BACKEND_URI=https://localhost:40443/ REACT_APP_AAD_AUTHORITY=https://login.microsoftonline.com/common -REACT_APP_AAD_CLIENT_ID= \ No newline at end of file +REACT_APP_AAD_CLIENT_ID= + +# If you add any new variables, make sure you update the variables list in the checkEnv.ts file as well. \ No newline at end of file diff --git a/samples/apps/copilot-chat-app/webapp/src/App.tsx b/samples/apps/copilot-chat-app/webapp/src/App.tsx index 0f73fd00ff1f..2ebf65bec009 100644 --- a/samples/apps/copilot-chat-app/webapp/src/App.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/App.tsx @@ -22,20 +22,18 @@ import { RootState } from './redux/app/store'; import { removeAlert } from './redux/features/app/appSlice'; import { CopilotChatTokens } from './styles'; -const useClasses = makeStyles({ +export const useClasses = makeStyles({ container: { + ...shorthands.overflow('hidden'), display: 'flex', flexDirection: 'column', width: '100%', height: '100vh', }, - content: { - Flex: 'auto', - }, header: { backgroundColor: CopilotChatTokens.backgroundColor, width: '100%', - height: '5.5%', + height: '48px', color: '#FFF', display: 'flex', '& h1': { @@ -119,37 +117,35 @@ const App: FC = () => { /> -
- {alerts && - Object.keys(alerts).map((key) => { - const alert = alerts[key]; - return ( - onDismissAlert(key)} - color="black" - /> - ), - }} - key={key} - > - {alert.message} - - ); - })} - {appState === AppState.ProbeForBackend && ( - setAppState(AppState.LoadingChats)} - /> - )} - {appState === AppState.LoadingChats && } - {appState === AppState.Chat && } -
+ {alerts && + Object.keys(alerts).map((key) => { + const alert = alerts[key]; + return ( + onDismissAlert(key)} + color="black" + /> + ), + }} + key={key} + > + {alert.message} + + ); + })} + {appState === AppState.ProbeForBackend && ( + setAppState(AppState.LoadingChats)} + /> + )} + {appState === AppState.LoadingChats && } + {appState === AppState.Chat && } diff --git a/samples/apps/copilot-chat-app/webapp/src/checkEnv.ts b/samples/apps/copilot-chat-app/webapp/src/checkEnv.ts new file mode 100644 index 000000000000..d6b36c23eeb0 --- /dev/null +++ b/samples/apps/copilot-chat-app/webapp/src/checkEnv.ts @@ -0,0 +1,14 @@ +export const getMissingEnvVariables = () => { + // Should be aligned with variables defined in env.example + const envVariables = ['REACT_APP_BACKEND_URI', 'REACT_APP_AAD_AUTHORITY', 'REACT_APP_AAD_CLIENT_ID']; + + const missingVariables = []; + + for (const variable of envVariables) { + if (!process.env[variable]) { + missingVariables.push(variable); + } + } + + return missingVariables; +}; diff --git a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatHistory.tsx b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatHistory.tsx index f0d6928cc27a..426cb515b493 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatHistory.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatHistory.tsx @@ -9,14 +9,13 @@ import { ChatStatus } from './ChatStatus'; const useClasses = makeStyles({ root: { + ...shorthands.gap(tokens.spacingVerticalM), display: 'flex', flexDirection: 'column', - ...shorthands.gap(tokens.spacingVerticalM), maxWidth: '900px', width: '100%', justifySelf: 'center', }, - content: {}, item: { display: 'flex', flexDirection: 'column', diff --git a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx index c7b5b6f9f3a8..e5fc363248a1 100644 --- a/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx +++ b/samples/apps/copilot-chat-app/webapp/src/components/chat/ChatInput.tsx @@ -23,7 +23,6 @@ const useClasses = makeStyles({ display: 'flex', flexDirection: 'column', ...shorthands.margin(0, '72px'), - alignContent: 'stretch', }, typingIndicator: { height: '28px', @@ -38,7 +37,7 @@ const useClasses = makeStyles({ width: '100%', }, textarea: { - height: '70px', + maxHeight: '80px', }, controls: { display: 'flex', @@ -52,7 +51,7 @@ const useClasses = makeStyles({ functional: { display: 'flex', flexDirection: 'row', - } + }, }); interface ChatInputProps { @@ -81,8 +80,7 @@ export const ChatInput: React.FC = (props) => { if (recognizer) return; void (async () => { var response = await speechService.validSpeechKeyAsync(); - if(response.isSuccess) - { + if (response.isSuccess) { const newRecognizer = await speechService.getSpeechRecognizerAsyncWithValidKey(response); setRecognizer(newRecognizer); } @@ -115,7 +113,7 @@ export const ChatInput: React.FC = (props) => { account!.homeAccountId!, selectedId, documentFile, - await AuthHelper.getSKaaSAccessToken(instance) + await AuthHelper.getSKaaSAccessToken(instance), ); dispatch(addAlert({ message: 'Document uploaded successfully', type: AlertType.Success })); } catch (e: any) { @@ -191,16 +189,26 @@ export const ChatInput: React.FC = (props) => { type="file" ref={documentFileRef} style={{ display: 'none' }} - accept='.txt,.pdf' + accept=".txt,.pdf" multiple={false} onChange={() => importDocument()} /> -