Skip to content

Commit

Permalink
Merge pull request #10 from Cognigy/messages-collation
Browse files Browse the repository at this point in the history
Messages collation
  • Loading branch information
kwinto authored Nov 30, 2023
2 parents ed5e89c + 41be480 commit b0c3d23
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 39 deletions.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ jobs:
with:
node-version: ${{ matrix.node-version }}
cache: "npm"
- run: npm run build
- run: npm ci
- run: npm run build
- run: npm test
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cognigy/chat-components",
"version": "0.3.1",
"version": "0.4.0",
"type": "module",
"exports": "./dist/chat-components.js",
"files": [
Expand Down
2 changes: 1 addition & 1 deletion src/common/MessageHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const MessageHeader: FC<MessageHeaderProps> = props => {
const recievedAt = message?.timestamp ? Number(message.timestamp) : Date.now();

return (
<header className={className}>
<header className={className} data-testid="message-header">
{props.enableAvatar && <Avatar />}
<div className={classes.headerMeta}>
{!isUserMessage && (
Expand Down
17 changes: 3 additions & 14 deletions src/demo.css
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,9 @@ body {
background-color: gray;
}
#root {
background-color: #fff;
font-family:
Figtree,
system-ui,
-apple-system,
BlinkMacSystemFont,
"Segoe UI",
Roboto,
Oxygen,
Ubuntu,
Cantarell,
"Open Sans",
"Helvetica Neue",
sans-serif;
background-color: #d9d9d9;
font-family: Figtree, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen,
Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;
margin-inline: auto;
width: 375px;
height: 620px;
Expand Down
38 changes: 23 additions & 15 deletions src/demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,39 @@ import { MessageSender } from "./messages/types.ts";
//fixtures
import listMessage from "test/fixtures/list.json";
import gallery from "test/fixtures/gallery.json";
import image from "test/fixtures/image.json";
import imageDownloadable from "test/fixtures/image-downloadable.json";
import image from "test/fixtures/image.json";
import imageBroken from "test/fixtures/imageBroken.json";
import video from "test/fixtures/video.json";
import videoYoutube from "test/fixtures/videoYoutube.json";
import audio from "test/fixtures/audio.json";
import { IMessage } from "@cognigy/socket-client";

const messages: MessageProps[] = [
{
message: {
text: "First message",
source: "bot",
timestamp: "1701163314138",
},
},
{
message: {
text: "Second message",
source: "bot",
timestamp: "1701163319138",
},
prevMessage: {
text: "Firts message",
source: "bot",
timestamp: "1701163314138",
},
},
{
message: {
avatarName: "Cognigy",
text: "",
source: "bot",
data: {
_cognigy: {
_webchat: {
Expand Down Expand Up @@ -49,6 +69,8 @@ const messages: MessageProps[] = [
{
message: {
avatarName: "Cognigy",
source: "bot",

data: {
_cognigy: {
_webchat: {
Expand Down Expand Up @@ -110,23 +132,9 @@ const messages: MessageProps[] = [
avatarName: "Cognigy",
},
},
{
message: {
source: "bot",
text: "This messaged is with previous with disableHeader prop",
avatarName: "Cognigy",
},
disableHeader: true,
},
{
message: image as IMessage,
},
{
message: {
source: "user",
text: "Nice cat. What about broken images?",
},
},
{
message: {
source: "bot",
Expand Down
1 change: 1 addition & 0 deletions src/messages/Image/Image.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ article .wrapper img {
}

.wrapperDownloadable {
background-color: var(--white);
cursor: pointer;
border: 1px solid var(--black-80);
}
Expand Down
6 changes: 5 additions & 1 deletion src/messages/Message.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@
color: var(--webchat-message-color, #1c1c1c);
font-weight: 400;
font-size: var(--webchat-message-font-size, 14px);
line-height: 1.3;
line-height: 1.4;
margin-block: var(--webchat-message-margin-block, 24px);
margin-inline: var(--webchat-message-margin-inline, 20px);
}

.collated {
margin-block-start: calc(var(--webchat-message-margin-block, 24px) * -0.5);
}
11 changes: 7 additions & 4 deletions src/messages/Message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { IWebchatConfig, MessageSender } from "./types";

import "src/theme.css";
import classes from "./Message.module.css";
import { isMessageCollatable } from "../utils";
import { IMessage } from "@cognigy/socket-client";

export interface MessageProps {
Expand All @@ -16,16 +17,20 @@ export interface MessageProps {
config?: IWebchatConfig;
disableHeader?: boolean;
message: IMessage;
plugins?: MatchConfig[];
onEmitAnalytics?: (event: string, payload?: unknown) => void;
plugins?: MatchConfig[];
prevMessage?: IMessage;
}

const Message: FC<MessageProps> = props => {
const shouldCollate = isMessageCollatable(props.message, props.prevMessage);

const rootClassName = classnames(
"webchat-message-row",
props.message.source,
props.className,
classes.message,
shouldCollate && classes.collated,
);

const MessageComponent = match(props.message, props.config, props.plugins);
Expand All @@ -45,9 +50,7 @@ const Message: FC<MessageProps> = props => {
config={props.config}
>
<article className={rootClassName}>
{!props.disableHeader && (
<MessageHeader enableAvatar={props.message.source !== "user"} />
)}
{!shouldCollate && <MessageHeader enableAvatar={props.message.source !== "user"} />}
<MessageComponent />
</article>
</MessageProvider>
Expand Down
12 changes: 12 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ export const getWebchatButtonLabel: getWebchatButtonLabel = button => {
return title;
};

export const isMessageCollatable = (message: IMessage, prevMessage?: IMessage) => {
const COLLATION_LIMIT = 1000 * 60; // 60 sec

const difference = Number(message?.timestamp) - Number(prevMessage?.timestamp);
return (
prevMessage &&
isNaN(difference) === false &&
difference < COLLATION_LIMIT &&
prevMessage?.source === message?.source
);
};

export const getBackgroundImage = (url: string) => {
if (!url) return undefined;

Expand Down
106 changes: 106 additions & 0 deletions test/Collation.spec.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { render } from "@testing-library/react";
import { it, describe, expect } from "vitest";
import Message from "../src/messages/Message";
import { IMessage } from "@cognigy/socket-client";

describe("Collation", () => {
it("collates if timestamp is in limit", () => {
const message1: IMessage = {
text: "Hello",
source: "bot",
timestamp: String(Date.now() - 1000 * 50),
};
const message2: IMessage = {
text: "World",
source: "bot",
timestamp: String(Date.now()),
};

const { getAllByTestId } = render(
<>
<Message message={message1} />
<Message message={message2} prevMessage={message1} />
</>,
);

const messageHeaders = getAllByTestId("message-header");
expect(messageHeaders).toHaveLength(1);
});

it("does NOT collate if timestamp is NOT in limit", () => {
const message1: IMessage = {
text: "Hello",
source: "bot",
timestamp: String(Date.now() - 1000 * 120),
};
const message2: IMessage = {
text: "World",
source: "bot",
timestamp: String(Date.now()),
};

const { getAllByTestId } = render(
<>
<Message message={message1} />
<Message message={message2} prevMessage={message1} />
</>,
);

const messageHeaders = getAllByTestId("message-header");
expect(messageHeaders).toHaveLength(2);
});

it("does NOT collate if source is different", () => {
const message1: IMessage = {
text: "Hello",
source: "bot",
timestamp: String(Date.now() - 1000),
};
const message2: IMessage = {
text: "World",
source: "user",
timestamp: String(Date.now()),
};

const { getAllByTestId } = render(
<>
<Message message={message1} />
<Message message={message2} prevMessage={message1} />
</>,
);

const messageHeaders = getAllByTestId("message-header");
expect(messageHeaders).toHaveLength(2);
});

it("collates multiple if all are in limit", () => {
const message1: IMessage = { text: "Hello", source: "user", timestamp: String(Date.now()) };
const message2: IMessage = {
text: "World",
source: "user",
timestamp: String(Date.now()),
};
const message3: IMessage = {
text: "World2",
source: "user",
timestamp: String(Date.now()),
};
const message4: IMessage = {
text: "World3",
source: "user",
timestamp: String(Date.now()),
};

const { getAllByTestId } = render(
<>
<Message message={message1} />
<Message message={message2} prevMessage={message1} />
<Message message={message3} prevMessage={message2} />
<Message message={message4} prevMessage={message3} />
</>,
);

const messageHeaders = getAllByTestId("message-header");
expect(messageHeaders).toHaveLength(1);
});
});

0 comments on commit b0c3d23

Please sign in to comment.