save bot chat messages

master
Tudor Stanciu 2020-06-07 04:12:20 +03:00
parent 3160cf9bd0
commit 93bb11a757
6 changed files with 92 additions and 18 deletions

View File

@ -15,7 +15,13 @@ export function loadBotSession(botName, userKey, botType) {
try { try {
const state = getState(); const state = getState();
const session = state.bot.session[botType]; const session = state.bot.session[botType];
if (session && (session.loading || session.loaded)) return; if (session && (session.loading || session.loaded)) {
//a session exists, so check if a chat is open
if (!state.bot.chat.loaded && !state.bot.chat.loading) {
dispatch(initializeChat(session.sessionId));
}
return;
}
dispatch({ type: types.INITIALIZE_BOT_SESSION_STARTED, botType }); dispatch({ type: types.INITIALIZE_BOT_SESSION_STARTED, botType });
const externalId = state.frontendSession.sessionId; const externalId = state.frontendSession.sessionId;
@ -30,14 +36,15 @@ export function loadBotSession(botName, userKey, botType) {
payload: data, payload: data,
botType botType
}); });
return data;
dispatch(initializeChat(data.sessionId));
} catch (error) { } catch (error) {
throw error; throw error;
} }
}; };
} }
export function initializeChat(sessionId) { function initializeChat(sessionId) {
return async function(dispatch) { return async function(dispatch) {
try { try {
dispatch({ type: types.INITIALIZE_BOT_CHAT_STARTED }); dispatch({ type: types.INITIALIZE_BOT_CHAT_STARTED });
@ -75,6 +82,16 @@ export function saveMessage(messageSourceId, messageDate, messageContent) {
return async function(dispatch, getState) { return async function(dispatch, getState) {
try { try {
const { chatId } = getState().bot.chat; const { chatId } = getState().bot.chat;
if (!chatId) {
//the chat is not yet initialized. The message will be stored on the client and sent to the server next time.
dispatch({
type: types.STORE_BOT_MESSAGE,
message: { messageSourceId, messageDate, messageContent }
});
return;
}
await dispatch(checkStorage(chatId));
const event = await dispatch( const event = await dispatch(
sendHttpRequest( sendHttpRequest(
api.saveMessage(chatId, messageSourceId, messageDate, messageContent) api.saveMessage(chatId, messageSourceId, messageDate, messageContent)
@ -87,3 +104,35 @@ export function saveMessage(messageSourceId, messageDate, messageContent) {
} }
}; };
} }
function checkStorage(chatId) {
return async function(dispatch, getState) {
try {
const messages = getState().bot.storage;
if (messages.length === 0) return;
const promises = [];
messages.forEach(message => {
const promise = dispatch(
sendHttpRequest(
api.saveMessage(
chatId,
message.messageSourceId,
message.messageDate,
message.messageContent
)
)
);
promises.push(promise);
});
//wait to save all stored messages to keep the order
await Promise.all(promises);
//clear stored messages after save
dispatch({ type: types.CLEAR_BOT_STORAGE });
} catch (error) {
throw error;
}
};
}

View File

@ -7,3 +7,5 @@ export const INITIALIZE_BOT_CHAT_STARTED = "INITIALIZE_BOT_CHAT_STARTED";
export const INITIALIZE_BOT_CHAT_SUCCESS = "INITIALIZE_BOT_CHAT_SUCCESS"; export const INITIALIZE_BOT_CHAT_SUCCESS = "INITIALIZE_BOT_CHAT_SUCCESS";
export const SAVE_BOT_MESSAGE_SUCCESS = "SAVE_BOT_MESSAGE_SUCCESS"; export const SAVE_BOT_MESSAGE_SUCCESS = "SAVE_BOT_MESSAGE_SUCCESS";
export const CLOSE_BOT_CHAT_SUCCESS = "CLOSE_BOT_CHAT_SUCCESS"; export const CLOSE_BOT_CHAT_SUCCESS = "CLOSE_BOT_CHAT_SUCCESS";
export const STORE_BOT_MESSAGE = "STORE_BOT_MESSAGE";
export const CLEAR_BOT_STORAGE = "CLEAR_BOT_STORAGE";

View File

@ -8,7 +8,6 @@ import { makeStyles } from "@material-ui/core/styles";
import { import {
dismissBot, dismissBot,
loadBotSession, loadBotSession,
initializeChat,
closeChat, closeChat,
saveMessage saveMessage
} from "../actionCreators"; } from "../actionCreators";
@ -34,11 +33,7 @@ const BotsManager = ({ bot, actions }) => {
setType(bot.type); setType(bot.type);
if (bot.type == botType.none) return; if (bot.type == botType.none) return;
actions actions.loadBotSession(bots.Zirhan, userKey.unknown, bot.type);
.loadBotSession(bots.Zirhan, userKey.unknown, bot.type)
.then(session => {
actions.initializeChat(session.sessionId);
});
}, [bot.type]); }, [bot.type]);
const dismissBot = () => { const dismissBot = () => {
@ -71,7 +66,7 @@ function mapStateToProps(state) {
function mapDispatchToProps(dispatch) { function mapDispatchToProps(dispatch) {
return { return {
actions: bindActionCreators( actions: bindActionCreators(
{ dismissBot, loadBotSession, initializeChat, closeChat, saveMessage }, { dismissBot, loadBotSession, closeChat, saveMessage },
dispatch dispatch
) )
}; };

View File

@ -4,7 +4,7 @@ import ChatBot from "react-simple-chatbot";
import { ThemeProvider } from "styled-components"; import { ThemeProvider } from "styled-components";
import { useTheme } from "@material-ui/core/styles"; import { useTheme } from "@material-ui/core/styles";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { bots } from "../constants"; import { bots, messageSource } from "../constants";
const Wizard = ({ dismissBot, saveMessage }) => { const Wizard = ({ dismissBot, saveMessage }) => {
const theme = useTheme(); const theme = useTheme();
@ -22,50 +22,68 @@ const Wizard = ({ dismissBot, saveMessage }) => {
userFontColor: "#4a4a4a" userFontColor: "#4a4a4a"
}; };
const getMessage = message => input => {
const currentDate = new Date();
let messageToSave = message;
if (message.includes("previousValue") && input.previousValue) {
messageToSave = message.replace("{previousValue}", input.previousValue);
}
saveMessage(messageSource.bot, currentDate, messageToSave);
return message;
};
const validate = text => {
const currentDate = new Date();
saveMessage(messageSource.user, currentDate, text);
return true;
};
const steps = [ const steps = [
{ {
id: "1", id: "1",
message: t("Chatbot.Wizard.Message1"), message: getMessage(t("Chatbot.Wizard.Message1")),
trigger: "2" trigger: "2"
}, },
{ {
id: "2", id: "2",
message: t("Chatbot.Wizard.Message2"), message: getMessage(t("Chatbot.Wizard.Message2")),
trigger: "3" trigger: "3"
}, },
{ {
id: "3", id: "3",
message: t("Chatbot.Wizard.Message3"), message: getMessage(t("Chatbot.Wizard.Message3")),
trigger: "4" trigger: "4"
}, },
{ {
id: "4", id: "4",
user: true, user: true,
validator: validate,
trigger: "5" trigger: "5"
}, },
{ {
id: "5", id: "5",
message: t("Chatbot.Wizard.Message5"), message: getMessage(t("Chatbot.Wizard.Message5")),
trigger: "6" trigger: "6"
}, },
{ {
id: "6", id: "6",
user: true, user: true,
validator: validate,
trigger: "7" trigger: "7"
}, },
{ {
id: "7", id: "7",
message: t("Chatbot.Wizard.Message7"), message: getMessage(t("Chatbot.Wizard.Message7")),
trigger: "8" trigger: "8"
}, },
{ {
id: "8", id: "8",
user: true, user: true,
validator: validate,
trigger: "9" trigger: "9"
}, },
{ {
id: "9", id: "9",
message: t("Chatbot.Wizard.Message9"), message: getMessage(t("Chatbot.Wizard.Message9")),
end: true end: true
} }
]; ];

View File

@ -44,6 +44,15 @@ export default function chatbotReducer(state = initialState.bot, action) {
case types.CLOSE_BOT_CHAT_SUCCESS: case types.CLOSE_BOT_CHAT_SUCCESS:
return { ...state, chat: initialState.bot.chat }; return { ...state, chat: initialState.bot.chat };
case types.STORE_BOT_MESSAGE: {
const storage = [...state.storage];
storage.push(action.message);
return { ...state, storage };
}
case types.CLEAR_BOT_STORAGE:
return { ...state, storage: initialState.bot.storage };
default: default:
return state; return state;
} }

View File

@ -21,7 +21,8 @@ export default {
bot: { bot: {
type: null, type: null,
session: {}, session: {},
chat: { loading: false, loaded: false } chat: { loading: false, loaded: false },
storage: []
}, },
ajaxCallsInProgress: 0 ajaxCallsInProgress: 0
}; };