Skip to content

Commit

Permalink
feat: add a user disclosure to appear before chat is functional (#15)
Browse files Browse the repository at this point in the history
This commit adds a disclosure that appears before the Xpert chatbot is functional. This disclosure must be shown to the user before they are able to use the chatbot.
  • Loading branch information
michaelroytman authored Aug 28, 2023
1 parent 3d59d0c commit fe1e428
Show file tree
Hide file tree
Showing 11 changed files with 217 additions and 79 deletions.
31 changes: 31 additions & 0 deletions src/components/Disclosure/Disclosure.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
@use '../../utils/variables';

.disclosure {
height: 100%;

overflow-y: auto;
background-color: variables.$dark-green;

h2 {
font-size: 2rem;
}

h3 {
color: variables.$accent-yellow;
}

p {
font-size: 0.625rem;
}

/* Due to CSS specificity of other typography selectors, selecting the a tag is not sufficient,
and we must add important. */
.privacy-policy-link {
text-decoration: underline !important;
text-decoration-color: white !important;
}

li {
font-size: 1rem;
}
}
67 changes: 67 additions & 0 deletions src/components/Disclosure/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React from 'react';
import { useDispatch } from 'react-redux';

import { Button, Hyperlink, Icon } from '@edx/paragon';
import { Chat } from '@edx/paragon/icons';
import { getConfig } from '@edx/frontend-platform/config';

import './Disclosure.scss';

import {
acknowledgeDisclosure,
} from '../../data/thunks';

const Disclosure = () => {
const dispatch = useDispatch();

const handleAcknowledgeDisclosure = () => {
dispatch(acknowledgeDisclosure(true));
};

return (
<div className="disclosure d-flex flex-column align-items-start px-4 py-3">
<h2 className="text-light-100">Xpert</h2>
<h3 className="small py-2">An AI-powered educational tool</h3>
<div className="d-flex flex-column">
<div className="text-light-100 d-flex flex-row">
<Icon src={Chat} className="m-2" />
<div>
Stuck on a concept? Need more clarification on a complicated topic?
<br />
Ask Xpert a question!
</div>
</div>
<div className="text-light-100 font-weight-light pl-3 my-2">
<ul>
<li>Could you explain how to multiply two numbers?</li>
<li>How should an essay be structured?</li>
<li>How does photosynthesis work?</li>
</ul>
</div>
</div>
<p className="text-light-100 py-3">
<strong>Note: </strong>
This chat is AI generated (powered by ChatGPT). Mistakes are possible.
By using it you agree that edX may create a record of this chat.
Your personal data will be used as described in our&nbsp;
<Hyperlink
className="privacy-policy-link text-light-100"
destination={getConfig().PRIVACY_POLICY_URL}
>
privacy policy
</Hyperlink>
.
</p>
<Button
onClick={handleAcknowledgeDisclosure}
variant="inverse-primary"
>
Let&apos;s get started.
</Button>
</div>
);
};

Disclosure.propTypes = {};

export default Disclosure;
7 changes: 4 additions & 3 deletions src/components/Message/Message.scss
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
@use '../../utils/variables';

.message {
width: fit-content;
max-width: 70%;
border-radius: 10px;
font-size: 15px;

&.user {
background:#EBEBEB;
background: variables.$dark-green;
}

&.assistant {
background:#0A3055;
color: white;
background: #F2F0EF;
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/components/Message/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const Message = ({ variant, message, timestamp }) => {

return (
<div
className={`message ${variant} ${variant === 'user' ? 'align-self-end' : ''} text-left my-1 mx-2 py-1 px-2`}
className={`message ${variant} ${variant === 'user' ? 'align-self-end' : 'text-dark'} text-left text-white my-1 mx-2 py-1 px-2`}
data-hj-suppress
>
{message}
Expand Down
37 changes: 19 additions & 18 deletions src/components/Sidebar/Sidebar.scss
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
@use '../../utils/variables';

.sidebar {
height: 100vh;
/* Set the height of the chat container */
overflow-y: scroll;
/* Enable vertical scrolling */
scroll-behavior: smooth;
/* Add smooth scrolling behavior */
box-shadow: 0 0 1rem 0 #00000026,0 0 .625rem 0 #00000026;
top: 0;
bottom: 0;
border-left-width: 1px;
border-color: #9CA3AF;
background-color: #F9FAFB;
background-color: white;

&.open {
width: 30%;
right: 0;
}
width: 30%;
right: 0;

/* Add smooth scrolling behavior */
scroll-behavior: smooth;

h1 {
font-size: 1.25rem;
Expand All @@ -29,6 +25,12 @@
right: 0;
background: none;

&.disclosure svg {
/* The default fill on the close button svg is too dark for the dark green background
of the disclosure, so use a white fill. */
fill: white;
}

svg {
width: 1.5rem;
height: 1.5rem;
Expand All @@ -46,8 +48,8 @@
padding-right: 0.75rem;
border-radius: 9999px;
border-style: solid;
background-color: #DBEAFE;
color: #1E3A8A;
background-color: variables.$dark-green;
color: white;
}

form {
Expand All @@ -58,13 +60,12 @@
border-style: solid;

&:hover {
outline-style: none;
border-color: #3B82F6;
border-color: variables.$dark-green;
}
}

button {
color: #1E3A8A;
color: variables.$dark-green;
background: none;
}
}
Expand Down
122 changes: 66 additions & 56 deletions src/components/Sidebar/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useRef, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Send } from 'react-feather';
import PropTypes from 'prop-types';
import Disclosure from '../Disclosure';
import ChatBox from '../ChatBox';
import APIError from '../APIError';
import './Sidebar.scss';
Expand All @@ -18,7 +19,12 @@ const Sidebar = ({
isOpen,
setIsOpen,
}) => {
const { messageList, currentMessage, apiError } = useSelector(state => state.learningAssistant);
const {
apiError,
currentMessage,
disclosureAcknowledged,
messageList,
} = useSelector(state => state.learningAssistant);
const chatboxContainerRef = useRef(null);
const dispatch = useDispatch();

Expand Down Expand Up @@ -82,16 +88,67 @@ const Sidebar = ({
dispatch(clearMessages());
};

const getSidebar = () => (
<div className="h-100 d-flex flex-column justify-content-stretch">
<div className="d-flex flex-column align-items-center p-3">
<h1 className="font-weight-bold mb-3 d-inline-flex flex-row">
Hi, I&apos;m Xpert!
<NewXeySvg width="20" className="pl-1" />
</h1>
<p className="px-3 mb-0 text-center">
Stuck on a concept? Need more clarification on a complicated topic?
Let&apos;s chat!
</p>
</div>
<span className="separator" />
<ChatBox
chatboxContainerRef={chatboxContainerRef}
messageList={messageList}
/>
{
apiError
&& (
<div className="d-flex flex-column p-3 mt-auto">
<APIError />
</div>
)
}
<form className={`d-flex flex-row p-2 ${apiError ? 'mt-1' : 'mt-auto'}`} onSubmit={handleSubmitMessage}>
<input
type="text"
value={currentMessage}
onChange={handleUpdateCurrentMessage}
placeholder="Type your question..."
className="w-100 p-3"
data-hj-suppress
/>
<button
className="mt-2 mb-1 mx-2 border-0"
type="submit"
data-testid="submit-button"
>
<Send size="22" className="ml-1" />
</button>
</form>
<div className="d-flex justify-content-start">
<button
className="clear mx-2 mb-2 border-0"
onClick={handleClearMessages}
type="button"
>
Clear
</button>
</div>
</div>
);

return (
isOpen && (
<div
className={
`sidebar d-flex flex-column justify-content-between position-fixed border-left 100-vh
${isOpen ? 'open' : ''}`
}
className="sidebar position-fixed"
>
<button
className="close position-absolute m-3 p-0 border-0"
className={`close position-absolute m-3 border-0 ${disclosureAcknowledged ? '' : 'disclosure'}`}
data-testid="close-button"
onClick={handleClick}
type="button"
Expand All @@ -103,57 +160,10 @@ const Sidebar = ({
<path d="M10 8.586L4.707 3.293a1 1 0 00-1.414 1.414L8.586 10l-5.293 5.293a1 1 0 101.414 1.414L10 11.414l5.293 5.293a1 1 0 001.414-1.414L11.414 10l5.293-5.293a1 1 0 00-1.414-1.414L10 8.586z" />
</svg>
</button>
<div className="d-flex flex-column align-items-center p-3">
<h1 className="font-weight-bold mb-3 d-inline-flex flex-row">
Hi, I&apos;m Xpert!
<NewXeySvg width="20" className="pl-1" />
</h1>
<p className="px-3 mb-0 text-center">
Stuck on a concept? Need more clarification on a complicated topic?
Let&apos;s chat!
</p>
</div>
<span className="separator" />
<ChatBox
chatboxContainerRef={chatboxContainerRef}
messageList={messageList}
/>
{
apiError
&& (
<div className="d-flex flex-column p-3 mt-auto">
<APIError />
</div>
)
}
<form className={`d-flex flex-row p-2 ${apiError ? 'mt-1' : 'mt-auto'}`} onSubmit={handleSubmitMessage}>
<input
type="text"
value={currentMessage}
onChange={handleUpdateCurrentMessage}
placeholder="Type your question..."
className="w-100 p-3"
data-hj-suppress
/>
<button
className="mt-2 mb-1 mx-2 border-0"
type="submit"
data-testid="submit-button"
>
<Send size="22" className="ml-1" />
</button>
</form>
<div className="d-flex justify-content-start">
<button
className="clear mx-2 mb-2 border-0"
onClick={handleClearMessages}
type="button"
>
Clear
</button>
</div>
{disclosureAcknowledged ? (getSidebar()) : (<Disclosure />)}
</div>
));
)
);
};

Sidebar.propTypes = {
Expand Down
4 changes: 3 additions & 1 deletion src/components/ToggleXpertButton/index.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
@use '../../utils/variables';

.open-negative-margin {
background-color: #0A3055;
background-color: variables.$dark-green;
border-radius: 10px;
bottom: 4rem;
}
Expand Down
5 changes: 5 additions & 0 deletions src/data/slice.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const learningAssistantSlice = createSlice({
apiError: false,
apiIsLoading: false,
conversationId: uuidv4(),
disclosureAcknowledged: false,
},
reducers: {
setCurrentMessage: (state, { payload }) => {
Expand All @@ -35,6 +36,9 @@ export const learningAssistantSlice = createSlice({
setApiIsLoading: (state, { payload }) => {
state.apiIsLoading = payload;
},
setDisclosureAcknowledged: (state, { payload }) => {
state.disclosureAcknowledged = payload;
},
},
});

Expand All @@ -46,6 +50,7 @@ export const {
setApiError,
setApiIsLoading,
resetApiError,
setDisclosureAcknowledged,
} = learningAssistantSlice.actions;

export const {
Expand Down
Loading

0 comments on commit fe1e428

Please sign in to comment.