Skip to content

Commit

Permalink
Release 1.4.0
Browse files Browse the repository at this point in the history
Release 1.4.0
  • Loading branch information
ggazzo authored Mar 20, 2020
2 parents 1e6ec37 + adb36b4 commit bbf38ca
Show file tree
Hide file tree
Showing 12 changed files with 146 additions and 39 deletions.
12 changes: 9 additions & 3 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@
All notable changes to this project will be documented in this file.
This project adheres to [Semantic Versioning](http://semver.org/).

## 1.4.0 - 2020-03-19
* [NEW] Add new API method the set the default Agent before chatting (#383)
* [NEW] Keep trigger messages after the conversation starts. (#384)
* [NEW] Widget API Methods (#381)
* [FIX] Livechat guest avatar using name instead of username (#380)

## 1.3.1 - 2020-02-12
* [FIX] Add Cross-tab communication on the same origin (#364)
* [FIX] Corrected German title for finished chat (#363)
* [FIX] Update polish translation (#324)
* [FIX] Add Cross-tab communication on the same origin (#364)
* [FIX] Corrected German title for finished chat (#363)
* [FIX] Update polish translation (#324)

## 1.3.0 - 2019-12-12
* [NEW] Add Service Offline callback (#341)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rocket.chat/livechat",
"version": "1.3.1",
"version": "1.4.0",
"files": [
"/build"
],
Expand Down
15 changes: 14 additions & 1 deletion src/components/Messages/Message/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,19 @@ const getSystemMessageText = ({ t, conversationFinishedMessage }) =>
|| (t === MESSAGE_TYPE_WELCOME && I18n.t('Welcome'))
|| (t === MESSAGE_TYPE_LIVECHAT_CLOSED && (conversationFinishedMessage || I18n.t('Conversation finished')));

const getMessageUsernames = (compact, message) => {
if (compact || !message.u) {
return [];
}

const { alias, u: { username, name } } = message;
if (alias && name) {
return [name];
}

return [username];
};

export const Message = memo(({
avatarResolver,
attachmentResolver = getAttachmentUrl,
Expand All @@ -88,7 +101,7 @@ export const Message = memo(({
>
<MessageAvatars
avatarResolver={avatarResolver}
usernames={compact ? [] : message.u && message.u.username && [message.u.username]}
usernames={getMessageUsernames(compact, message)}
/>
<MessageContent reverse={me}>
{renderContent({
Expand Down
6 changes: 6 additions & 0 deletions src/components/Messages/MessageAvatars/stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ storiesOf('Messages|MessageAvatars', module)
avatarResolver={avatarResolver}
usernames={object('usernames', ['guilherme.gazzo', 'tasso.evangelista', 'martin.schoeler'])}
/>
))
.add('with name as avatar instead of username for guests', () => (
<MessageAvatars
avatarResolver={avatarResolver}
usernames={object('usernames', ['livechat guest'])}
/>
));
23 changes: 20 additions & 3 deletions src/lib/hooks.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import { parentCall } from './parentCall';
const createOrUpdateGuest = async (guest) => {
const { token } = guest;
token && await store.setState({ token });
await Livechat.grantVisitor({ visitor: { ...guest } });
await loadConfig();
const user = await Livechat.grantVisitor({ visitor: { ...guest } });
store.setState({ user });
};

const updateIframeGuestData = (data) => {
Expand Down Expand Up @@ -42,7 +42,7 @@ const api = {
CustomFields.setCustomField(key, value, overwrite);
},

setTheme({ color, fontColor, iconColor } = {}) {
setTheme({ color, fontColor, iconColor, title, offlineTitle } = {}) {
const { iframe, iframe: { theme } } = store.state;
store.setState({
iframe: {
Expand All @@ -52,6 +52,8 @@ const api = {
color,
fontColor,
iconColor,
title,
offlineTitle,
},
},
});
Expand All @@ -70,6 +72,21 @@ const api = {
updateIframeGuestData({ department: '' });
},

setAgent({ _id, username, ...props } = {}) {
if (!_id || !username) {
return console.warn('The fields _id and username are mandatory.');
}

store.setState({
defaultAgent: {
_id,
username,
ts: Date.now(),
...props,
},
});
},

setExpanded(expanded) {
store.setState({ expanded });
},
Expand Down
17 changes: 10 additions & 7 deletions src/lib/room.js
Original file line number Diff line number Diff line change
Expand Up @@ -149,20 +149,19 @@ Livechat.onMessage(async (message) => {
});

export const loadMessages = async () => {
const { room: { _id: rid } = {} } = store.state;
const { messages: storedMessages, room: { _id: rid } = {} } = store.state;
const previousMessages = getGreetingMessages(storedMessages);

if (!rid) {
return;
}

await store.setState({ loading: true });

const rawMessages = await Livechat.loadMessages(rid);
const rawMessages = (await Livechat.loadMessages(rid)).concat(previousMessages);
const messages = (await normalizeMessages(rawMessages)).map(transformAgentInformationOnMessage);

await initRoom();
await store.setState({ messages: (messages || []).reverse(), noMoreMessages: false });
await store.setState({ loading: false });
await store.setState({ messages: (messages || []).reverse(), noMoreMessages: false, loading: false });

if (messages && messages.length) {
const lastMessage = messages[messages.length - 1];
Expand All @@ -185,21 +184,25 @@ export const loadMoreMessages = async () => {
await store.setState({
messages: (moreMessages || []).reverse(),
noMoreMessages: messages.length + 10 > moreMessages.length,
loading: false,
});
await store.setState({ loading: false });
};

export const defaultRoomParams = () => {
const params = {};

const { triggerAgent: { agent } = {} } = store.state;
const { defaultAgent: agent = {} } = store.state;
if (agent && agent._id) {
Object.assign(params, { agentId: agent._id });
}

return params;
};

export const getGreetingMessages = (messages) => {
return messages && messages.filter((msg) => msg.trigger);
}

store.on('change', (state, prevState) => {
// Cross-tab communication
// Detects when a room is created and then route to the correct container
Expand Down
14 changes: 5 additions & 9 deletions src/lib/triggers.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,9 @@ const getAgent = (triggerAction) => {

if (params.sender === 'queue') {
const { state } = store;
const { triggerAgent, iframe: { guest: { department } } } = state;

if (triggerAgent) {
const cacheAgent = triggerAgent;
// cache valid for 1h
if (cacheAgent.ts && Date.now() - cacheAgent.ts < agentCacheExpiry) {
return resolve(cacheAgent.agent);
}
const { defaultAgent, iframe: { guest: { department } } } = state;
if (defaultAgent && defaultAgent.ts && Date.now() - defaultAgent.ts < agentCacheExpiry) {
return resolve(defaultAgent); // cache valid for 1
}

let agent;
Expand All @@ -36,7 +31,7 @@ const getAgent = (triggerAction) => {
return reject(error);
}

store.setState({ triggerAgent: { agent, ts: Date.now() } });
store.setState({ defaultAgent: { ...agent, ts: Date.now() } });
resolve(agent);
} else if (params.sender === 'custom') {
resolve({
Expand Down Expand Up @@ -114,6 +109,7 @@ class Triggers {
u: agent,
ts: ts.toISOString(),
_id: createToken(),
trigger: true,
};

await store.setState({
Expand Down
18 changes: 11 additions & 7 deletions src/routes/Chat/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import constants from '../../lib/constants';
import { createToken, debounce, getAvatarUrl, canRenderMessage, throttle, upsert } from '../../components/helpers';
import Chat from './component';
import { ModalManager } from '../../components/Modal';
import { initRoom, closeChat, loadMessages, loadMoreMessages, defaultRoomParams } from '../../lib/room';
import { initRoom, closeChat, loadMessages, loadMoreMessages, defaultRoomParams, getGreetingMessages } from '../../lib/room';
import { normalizeQueueAlert } from '../../lib/api';

export class ChatContainer extends Component {
Expand Down Expand Up @@ -48,19 +48,20 @@ export class ChatContainer extends Component {
}

grantUser = async () => {
const { token, user, guest } = this.props;
const { token, user, guest, dispatch } = this.props;

if (user) {
return user;
}

const visitor = { token, ...guest };
await Livechat.grantVisitor({ visitor });
await loadConfig();
const newUser = await Livechat.grantVisitor({ visitor });
await dispatch({ user: newUser });
}

getRoom = async () => {
const { alerts, dispatch, room } = this.props;
const { alerts, dispatch, room, messages } = this.props;
const previousMessages = getGreetingMessages(messages);

if (room) {
return room;
Expand All @@ -70,7 +71,7 @@ export class ChatContainer extends Component {
try {
const params = defaultRoomParams();
const newRoom = await Livechat.room(params);
await dispatch({ room: newRoom, messages: [], noMoreMessages: false });
await dispatch({ room: newRoom, messages: previousMessages, noMoreMessages: false });
await initRoom();

parentCall('callback', 'chat-started');
Expand Down Expand Up @@ -117,6 +118,7 @@ export class ChatContainer extends Component {
await this.grantUser();
const { _id: rid } = await this.getRoom();
const { alerts, dispatch, token, user } = this.props;

try {
this.stopTypingDebounced.stop();
await Promise.all([
Expand Down Expand Up @@ -353,6 +355,7 @@ export const ChatConnector = ({ ref, ...props }) => (
color: customColor,
fontColor: customFontColor,
iconColor: customIconColor,
title: customTitle,
} = {},
guest,
} = {},
Expand Down Expand Up @@ -380,8 +383,9 @@ export const ChatConnector = ({ ref, ...props }) => (
color: customColor || color,
fontColor: customFontColor,
iconColor: customIconColor,
title: customTitle,
}}
title={title || I18n.t('Need help?')}
title={customTitle || title || I18n.t('Need help?')}
sound={sound}
token={token}
user={user}
Expand Down
12 changes: 10 additions & 2 deletions src/routes/LeaveMessage/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ export const LeaveMessageConnector = ({ ref, ...props }) => (
displayOfflineForm,
} = {},
} = {},
iframe: {
theme: {
offlineTitle: customOfflineTitle,
} = {},
} = {},
loading,
token,
dispatch,
Expand All @@ -59,8 +64,11 @@ export const LeaveMessageConnector = ({ ref, ...props }) => (
<LeaveMessageContainer
ref={ref}
{...props}
title={title}
theme={{ color }}
theme={{
color,
offlineTitle: customOfflineTitle,
}}
title={customOfflineTitle || title}
message={message}
successMessage={successMessage}
unavailableMessage={unavailableMessage}
Expand Down
8 changes: 5 additions & 3 deletions src/routes/Register/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ export class RegisterContainer extends Component {

await dispatch({ loading: true, department });
try {
await Livechat.grantVisitor({ visitor: { ...fields, token } });
const user = await Livechat.grantVisitor({ visitor: { ...fields, token } });
await dispatch({ user });
parentCall('callback', ['pre-chat-form-submit', fields]);
await loadConfig();
} finally {
await dispatch({ loading: false });
}
Expand Down Expand Up @@ -85,6 +85,7 @@ export const RegisterConnector = ({ ref, ...props }) => (
color: customColor,
fontColor: customFontColor,
iconColor: customIconColor,
title: customTitle,
} = {},
} = {},
loading = false,
Expand All @@ -99,8 +100,9 @@ export const RegisterConnector = ({ ref, ...props }) => (
color: customColor || color,
fontColor: customFontColor,
iconColor: customIconColor,
title: customTitle,
}}
title={title}
title={customTitle || title}
message={message}
hasNameField={hasNameField}
hasEmailField={hasEmailField}
Expand Down
5 changes: 2 additions & 3 deletions src/routes/SwitchDepartment/container.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ export class SwitchDepartmentContainer extends Component {
}

if (!room) {
await Livechat.grantVisitor({ visitor: { department, token } });
await loadConfig();
await dispatch({ alerts: (alerts.push({ id: createToken(), children: I18n.t('Department switched'), success: true }), alerts) });
const user = await Livechat.grantVisitor({ visitor: { department, token } });
await dispatch({ user, alerts: (alerts.push({ id: createToken(), children: I18n.t('Department switched'), success: true }), alerts) });
return history.go(-1);
}

Expand Down
Loading

0 comments on commit bbf38ca

Please sign in to comment.