Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
…_front into feat/#48
  • Loading branch information
seohyun319 committed Mar 26, 2022
2 parents b719f19 + cf71c58 commit cc99031
Show file tree
Hide file tree
Showing 23 changed files with 678 additions and 42 deletions.
10 changes: 10 additions & 0 deletions thisable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,26 @@
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.3",
"@testing-library/user-event": "^13.5.0",
"antd": "^3.26.5",
"axios": "^0.26.1",
"prop-types": "^15.7.2",
"bootstrap": "^5.1.3",
"dotenv": "^16.0.0",
"geolocation": "^0.2.0",
"package.json": "^2.0.1",
"react": "^17.0.2",
"react-bootstrap": "^2.1.2",
"react-dom": "^17.0.2",
"react-redux": "^7.1.3",
"react-geolocated": "^3.2.0",
"react-router-dom": "^6.2.2",
"react-scripts": "5.0.0",
"react-simple-star-rating": "^4.0.5",
"react-star-ratings": "^2.3.0",
"redux": "^4.0.5",
"redux-promise": "^0.6.0",
"redux-thunk": "^2.3.0",
"uuid": "^3.3.2",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand All @@ -46,5 +53,8 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"http-proxy-middleware": "^0.19.1"
}
}
8 changes: 8 additions & 0 deletions thisable/src/_actions/message_actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { SAVE_MESSAGE } from "./types";

export function saveMessage(dataToSubmit) {
return {
type: SAVE_MESSAGE,
payload: dataToSubmit,
};
}
1 change: 1 addition & 0 deletions thisable/src/_actions/types.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const SAVE_MESSAGE = "save_message";
8 changes: 8 additions & 0 deletions thisable/src/_reducers/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { combineReducers } from "redux";
import message from "./message_reducer";

const rootReducer = combineReducers({
message,
});

export default rootReducer;
13 changes: 13 additions & 0 deletions thisable/src/_reducers/message_reducer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { SAVE_MESSAGE } from "../_actions/types";

export default function (state = { messages: [] }, action) {
switch (action.type) {
case SAVE_MESSAGE:
return {
...state,
messages: state.messages.concat(action.payload),
};
default:
return state;
}
}
3 changes: 3 additions & 0 deletions thisable/src/assets/images/thumbs_down.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 10 additions & 0 deletions thisable/src/assets/images/thumbs_up.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
39 changes: 39 additions & 0 deletions thisable/src/components/Chatbot/Chatbot.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
* {
word-break: keep-all;
overflow-wrap: break-word;
word-wrap: break-word;
}

.chatbotModal {
background-color: #e599b3;
width: 5rem;
height: 5rem;
border-radius: 10px;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
position: fixed;
right: 50px;
bottom: 50px;
box-shadow: 0 10px 10px rgb(0 0 0 / 30%);
}

.robotBtn > svg {
width: 4rem;
height: 4rem;
}

.ant-list-item-meta-content {
max-width: 500px;
overflow-x: none;
}

.ant-list-item-meta-title {
font-size: 20px !important;
}

.ant-list-item-meta-description {
display: flex;
color: black !important;
}
180 changes: 180 additions & 0 deletions thisable/src/components/Chatbot/Chatbot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import React, { useEffect } from "react";
import Axios from "axios";
import { useDispatch, useSelector } from "react-redux";
import { saveMessage } from "../../_actions/message_actions";
import Message from "./Sections/Message";
import { List, Icon, Avatar } from "antd";
import Card from "./Sections/Card";
import "./Chatbot.css";

function Chatbot() {
const dispatch = useDispatch();
const messagesFromRedux = useSelector((state) => state.message.messages);

useEffect(() => {
eventQuery("welcomeToMyWebsite");
}, []);

const textQuery = async (text) => {
// First Need to take care of the message I sent
let conversation = {
who: "user",
content: {
text: {
text: text,
},
},
};

dispatch(saveMessage(conversation));
// console.log('text I sent', conversation)

// We need to take care of the message Chatbot sent
const textQueryVariables = {
text, //== text: text
};
try {
//I will send request to the textQuery ROUTE
const response = await Axios.post(
"/api/dialogflow/textQuery",
textQueryVariables
);

for (let content of response.data.fulfillmentMessages) {
conversation = {
who: "bot",
content: content,
};

dispatch(saveMessage(conversation));
}
} catch (error) {
conversation = {
who: "bot",
content: {
text: {
text: " Error just occured, please check the problem",
},
},
};
dispatch(saveMessage(conversation));
}
};

const eventQuery = async (event) => {
// We need to take care of the message Chatbot sent
const eventQueryVariables = {
event,
};
try {
//I will send request to the textQuery ROUTE
const response = await Axios.post(
"/api/dialogflow/eventQuery",
eventQueryVariables
);
for (let content of response.data.fulfillmentMessages) {
let conversation = {
who: "bot",
content: content,
};
dispatch(saveMessage(conversation));
}
} catch (error) {
let conversation = {
who: "bot",
content: {
text: {
text: " Error just occured, please check the problem",
},
},
};
dispatch(saveMessage(conversation));
}
};

const keyPressHanlder = (e) => {
if (e.key === "Enter") {
if (!e.target.value) {
return alert("you need to type somthing first");
}

//we will send request to text query route
textQuery(e.target.value);
e.target.value = "";
}
};

const renderCards = (cards) => {
return cards.map((card, i) => <Card key={i} cardInfo={card.structValue} />);
};

const renderOneMessage = (message, i) => {
console.log("message", message);
// we need to give some condition here to separate message kinds

// template for normal text
if (message.content && message.content.text && message.content.text.text) {
return (
<Message key={i} who={message.who} text={message.content.text.text} />
);
} else if (message.content && message.content.payload.fields.card) {
const AvatarSrc =
message.who === "bot" ? <Icon type="robot" /> : <Icon type="smile" />;

return (
<div>
<List.Item style={{ padding: "1rem" }}>
<List.Item.Meta
avatar={<Avatar icon={AvatarSrc} />}
title={message.who}
description={renderCards(
message.content.payload.fields.card.listValue.values
)}
/>
</List.Item>
</div>
);
}
// template for card message
};

const renderMessage = (returnedMessages) => {
if (returnedMessages) {
return returnedMessages.map((message, i) => {
return renderOneMessage(message, i);
});
} else {
return null;
}
};

return (
<div
style={{
height: 450,
width: 450,
border: "5px solid black",
borderRadius: "7px",
}}
>
<div style={{ height: 390, width: "100%", overflow: "auto" }}>
{renderMessage(messagesFromRedux)}
</div>
<input
style={{
margin: 0,
width: "100%",
height: 50,
borderRadius: "1px",
padding: "5px",
fontSize: "1rem",
}}
placeholder="Send a message..."
onKeyPress={keyPressHanlder}
type="text"
/>
</div>
);
}

export default Chatbot;
32 changes: 32 additions & 0 deletions thisable/src/components/Chatbot/ChatbotModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React, { useState } from "react";
import { Modal } from "react-bootstrap";
import { Icon, Avatar } from "antd";
import Chatbot from "./Chatbot";

function ChatbotModal() {
const [modalShow, setModalShow] = useState(false);

return (
<>
<div onClick={() => setModalShow(true)} className="chatbotModal">
<Icon type="robot" className="robotBtn" />
</div>
<Modal show={modalShow} onHide={() => setModalShow(false)}>
<Modal.Header closeButton>thisABLE Chatbot</Modal.Header>
<Modal.Body>
<div
style={{
display: "flex",
justifyContent: "center",
}}
></div>
<div style={{ display: "flex", justifyContent: "center" }}>
<Chatbot />
</div>
</Modal.Body>
</Modal>
</>
);
}

export default ChatbotModal;
36 changes: 36 additions & 0 deletions thisable/src/components/Chatbot/Sections/Card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from "react";
import { Card, Icon } from "antd";

const { Meta } = Card;

function CardComponent(props) {
const cardwidth = props.cardInfo.fields.cardWidth.stringValue;
return (
<Card
style={{ width: "300px" }}
cover={
<a
target="_blank"
rel="noopener noreferrer"
href={props.cardInfo.fields.link.stringValue}
>
<img
alt={props.cardInfo.fields.description.stringValue}
src={props.cardInfo.fields.image.stringValue}
style={{ width: cardwidth, height: "150px", objectFit: "cover" }}
/>
</a>
}
// actions={[
// <Icon type="ellipsis" key="ellipsis" />
// ]}
>
<Meta
title={props.cardInfo.fields.stack.stringValue}
description={props.cardInfo.fields.description.stringValue}
/>
</Card>
);
}

export default CardComponent;
19 changes: 19 additions & 0 deletions thisable/src/components/Chatbot/Sections/Message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import React from "react";
import { List, Icon, Avatar } from "antd";

function Message(props) {
const AvatarSrc =
props.who === "bot" ? <Icon type="robot" /> : <Icon type="smile" />;

return (
<List.Item style={{ padding: "1rem" }}>
<List.Item.Meta
avatar={<Avatar icon={AvatarSrc} />}
title={props.who}
description={props.text}
/>
</List.Item>
);
}

export default Message;
Loading

0 comments on commit cc99031

Please sign in to comment.