Skip to content

Commit 48d9ce5

Browse files
committed
feat(add and remove tags): allow adding and removing tags
1 parent 95e8a5f commit 48d9ce5

File tree

10 files changed

+218
-23
lines changed

10 files changed

+218
-23
lines changed

packages/client-graphql/src/inbox/index.ts

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export default (
1818
| ICourierClientJWTParams
1919
| { client?: Client }
2020
): {
21+
addTag: TrackEvent;
2122
getInboxCount: GetInboxCount;
2223
getMessage: message.GetInboxMessage;
2324
getMessageLists: messageLists.GetInboxMessageLists;
@@ -27,6 +28,7 @@ export default (
2728
markOpened: TrackEvent;
2829
markRead: TrackEvent;
2930
markUnread: TrackEvent;
31+
removeTag: TrackEvent;
3032
trackClick: TrackEvent;
3133
unpinMessage: TrackEvent;
3234
} => {
@@ -35,6 +37,8 @@ export default (
3537
});
3638

3739
return {
40+
addTag: trackEvent(client)("addTag"),
41+
removeTag: trackEvent(client)("removeTag"),
3842
getInboxCount: getInboxCount(client),
3943
getMessage: message.getInboxMessage(client),
4044
getMessageLists: messageLists.getMessageLists(client),

packages/client-graphql/src/inbox/track-event.ts

+54-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import { Client } from "urql";
22

3-
type EventType = "read" | "unread" | "archive" | "opened" | "clicked" | "unpin";
3+
type EventType =
4+
| "addTag"
5+
| "archive"
6+
| "clicked"
7+
| "opened"
8+
| "read"
9+
| "removeTag"
10+
| "unpin"
11+
| "unread";
12+
413
export const getTrackEventQuery = (eventType: EventType) => `
514
mutation TrackEvent(
615
$messageId: String!
@@ -9,6 +18,15 @@ export const getTrackEventQuery = (eventType: EventType) => `
918
}
1019
`;
1120

21+
export const getTagMutation = (eventType: EventType) => `
22+
mutation TrackEvent(
23+
$messageId: String!
24+
$tag: String!
25+
) {
26+
${eventType}(messageId: $messageId, tag: $tag)
27+
}
28+
`;
29+
1230
export const getTrackEventQueryWithTrackingId = (eventType: EventType) => `
1331
mutation TrackEvent(
1432
$messageId: String!
@@ -28,18 +46,47 @@ export type TrackEvent = (messageId: string) => Promise<
2846
export const trackEvent =
2947
(client?: Client) =>
3048
(eventType: EventType): TrackEvent =>
31-
async (messageId: string, trackingId?: string) => {
49+
async (messageId: string, data?: Record<string, unknown>) => {
3250
if (!client) {
3351
return Promise.resolve(undefined);
3452
}
3553

36-
const QUERY =
37-
eventType === "clicked"
38-
? getTrackEventQueryWithTrackingId(eventType)
39-
: getTrackEventQuery(eventType);
54+
const params = (() => {
55+
switch (eventType) {
56+
case "clicked": {
57+
return {
58+
mutation: getTrackEventQueryWithTrackingId(eventType),
59+
variables: {
60+
messageId,
61+
trackingId: data?.trackingId,
62+
},
63+
};
64+
}
65+
66+
case "addTag":
67+
case "removeTag": {
68+
return {
69+
mutation: getTagMutation(eventType),
70+
variables: {
71+
messageId,
72+
tag: data?.tag,
73+
},
74+
};
75+
}
76+
77+
default: {
78+
return {
79+
mutation: getTrackEventQuery(eventType),
80+
variables: {
81+
messageId,
82+
},
83+
};
84+
}
85+
}
86+
})();
4087

4188
const results = await client
42-
.mutation(QUERY, { messageId, trackingId })
89+
.mutation(params.mutation, params.variables)
4390
.toPromise();
4491
const status = results?.data?.[eventType];
4592

packages/components/src/index.html

+21-8
Original file line numberDiff line numberDiff line change
@@ -271,19 +271,32 @@
271271
};*/
272272

273273
window.courierConfig = {
274+
/*
275+
STAGING CONFIG
276+
274277
inboxApiUrl:
275-
"https://3rjq5oe9b1.execute-api.us-east-1.amazonaws.com/dev/q",
278+
"https://4rq7n8hhjd.execute-api.us-east-1.amazonaws.com/staging/q",
276279
apiUrl:
277-
"https://rubmz24skk.execute-api.us-east-1.amazonaws.com/dev/client/q",
280+
"https://yubmnstah4.execute-api.us-east-1.amazonaws.com/staging/client/q",
278281
wsOptions: {
279-
url: "wss://20en15n3ng.execute-api.us-east-1.amazonaws.com/dev",
282+
url: "wss://icnrz8ttcf.execute-api.us-east-1.amazonaws.com/staging",
280283
},
281-
clientKey: "ZDJmNTVhMWQtYmZjMS00ODg0LThhMjQtZDg0ZDg5ZTlhN2Ri",
282-
// JWT SMOKEY
283-
//clientKey: "YzQzMGM3OGYtYzQ2NC00NTdjLThkM2QtNWIwYzI4OTdmYmE5",
284-
//userId: "smokey12345",
284+
clientKey: "MWIxZTk1M2YtMGViYi00N2FkLWJlYWItZjU3OWJkNjA2ZWIx=",
285+
userId: "smokey12345",*/
286+
//authorization: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzY29wZSI6InVzZXJfaWQ6MDB1ZDZjZGRlY1VSaEhybWkzNTcgaW5ib3g6cmVhZDptZXNzYWdlcyBpbmJveDp3cml0ZTpldmVudHMiLCJ0ZW5hbnRfc2NvcGUiOiJwdWJsaXNoZWQvdGVzdCIsInRlbmFudF9pZCI6ImJiNjAyNDM5LTI2MmYtNGRlZS1iNDExLTNiZjdmMjM5NDYyMS90ZXN0IiwiYWNjb3VudF9pZCI6IjAxRkdTN1hWVDlBSEo4OE43QVpCMDE5UUdaIiwiaWF0IjoxNzEwNDYyMjg5LCJqdGkiOiJmMTc3NWJlMi1hNzVhLTQxNDktYjNhMC02YjA0MjdhNzg0NjQifQ.8FwrFCKPyFP1MCIH8kWBWfWCUUGDyP5w4oYuQGPWGtY",
285287

286-
userId: "70f6a4f4-2907-4518-b8f3-b9cfab224764",
288+
//userId: "70f6a4f4-2907-4518-b8f3-b9cfab224764",
289+
290+
// rileydev config
291+
inboxApiUrl:
292+
"https://3gbm33p3pe.execute-api.us-east-1.amazonaws.com/dev/q",
293+
apiUrl:
294+
"https://ln3nzc1ca8.execute-api.us-east-1.amazonaws.com/dev/client/q",
295+
wsOptions: {
296+
url: "wss://p46x8j3l88.execute-api.us-east-1.amazonaws.com/dev",
297+
},
298+
clientKey: "NDBmYTEyODAtNjg0Ni00YjYwLTlkZjktNGE3M2RkMWM4ZWIw",
299+
userId: "ed633018-217c-4b2d-a2e9-0548f0955bdc",
287300
components: {
288301
inbox: {
289302
appendTo: "#test",

packages/components/src/index.tsx

-3
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,6 @@ const initCourier = (courierConfig?: ICourierConfig) => {
107107
return;
108108
}
109109

110-
if (!userId || !clientKey) {
111-
return;
112-
}
113110
const existingCourierRoot =
114111
document.getElementsByTagName("courier-root")?.[0];
115112

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type AddTag = {
2+
type: "inbox/ADD_TAG";
3+
payload: {
4+
tag: string;
5+
messageId: string;
6+
};
7+
};
8+
9+
export const INBOX_ADD_TAG = "inbox/ADD_TAG";
10+
11+
export const addTag = (messageId: string, tag: string): AddTag => ({
12+
type: INBOX_ADD_TAG,
13+
payload: {
14+
tag,
15+
messageId,
16+
},
17+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
export type RemoveTag = {
2+
type: "inbox/REMOVE_TAG";
3+
payload: {
4+
tag: string;
5+
messageId: string;
6+
};
7+
};
8+
9+
export const INBOX_REMOVE_TAG = "inbox/REMOVE_TAG";
10+
11+
export const removeTag = (messageId: string, tag: string): RemoveTag => ({
12+
type: INBOX_REMOVE_TAG,
13+
payload: {
14+
tag,
15+
messageId,
16+
},
17+
});

packages/react-hooks/src/inbox/reducer.ts

+54
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import {
1212
ResetLastFetched,
1313
INBOX_RESET_LAST_FETCHED,
1414
} from "./actions/reset-last-fetched";
15+
import { AddTag, INBOX_ADD_TAG } from "./actions/add-tag";
16+
import { RemoveTag, INBOX_REMOVE_TAG } from "./actions/remove-tag";
17+
1518
import {
1619
MarkMessageArchived,
1720
INBOX_MARK_MESSAGE_ARCHIVED,
@@ -49,6 +52,7 @@ export const initialState: IInbox = {
4952
};
5053

5154
type InboxAction =
55+
| AddTag
5256
| FetchMessagesDone
5357
| FetchMessagesError
5458
| FetchMessagesPending
@@ -61,6 +65,7 @@ type InboxAction =
6165
| MarkMessageRead
6266
| MarkMessageUnread
6367
| NewMessage
68+
| RemoveTag
6469
| ResetLastFetched
6570
| ToggleInbox
6671
| UnpinMessage;
@@ -249,6 +254,55 @@ export default (state: IInbox = initialState, action?: InboxAction): IInbox => {
249254
};
250255
}
251256

257+
case INBOX_ADD_TAG: {
258+
const handleAddTag = (message: IInboxMessagePreview) => {
259+
if (message.messageId === action.payload.messageId) {
260+
const tags = message.tags ?? [];
261+
if (!tags.includes(action.payload.tag)) {
262+
tags.push(action.payload.tag);
263+
}
264+
return {
265+
...message,
266+
tags,
267+
};
268+
}
269+
270+
return message;
271+
};
272+
273+
const newPinned = state.pinned?.map(handleAddTag);
274+
const newMessages = state.messages?.map(handleAddTag);
275+
276+
return {
277+
...state,
278+
pinned: newPinned,
279+
messages: newMessages,
280+
};
281+
}
282+
283+
case INBOX_REMOVE_TAG: {
284+
const handleRemoveTag = (message: IInboxMessagePreview) => {
285+
if (message.messageId === action.payload.messageId) {
286+
const tags = message?.tags?.filter((t) => t !== action.payload.tag);
287+
return {
288+
...message,
289+
tags,
290+
};
291+
}
292+
293+
return message;
294+
};
295+
296+
const newPinned = state.pinned?.map(handleRemoveTag);
297+
const newMessages = state.messages?.map(handleRemoveTag);
298+
299+
return {
300+
...state,
301+
pinned: newPinned,
302+
messages: newMessages,
303+
};
304+
}
305+
252306
case INBOX_UNPIN_MESSAGE: {
253307
const pinned = state.pinned ?? [];
254308
const messageToUnpin = pinned?.find((p) => {

packages/react-hooks/src/inbox/use-inbox-actions.ts

+42
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ import { resetLastFetched } from "./actions/reset-last-fetched";
1919
import { setView } from "./actions/set-view";
2020
import { toggleInbox } from "./actions/toggle-inbox";
2121
import { unpinMessage } from "./actions/unpin-message";
22+
import { addTag } from "./actions/add-tag";
23+
import { removeTag } from "./actions/remove-tag";
2224

2325
import { useEffect } from "react";
2426
import { markMessageOpened } from "./actions/mark-message-opened";
@@ -44,6 +46,12 @@ export interface IInboxActions {
4446
setView: (view: string | "preferences") => void;
4547
toggleInbox: (isOpen?: boolean) => void;
4648
unpinMessage: (messageId: string, fromWS?: boolean) => Promise<void>;
49+
addTag: (messageId: string, tag: string, fromWS?: boolean) => Promise<void>;
50+
removeTag: (
51+
messageId: string,
52+
tag: string,
53+
fromWS?: boolean
54+
) => Promise<void>;
4755
trackClick: (messageId: string, trackingId: string) => Promise<void>;
4856
}
4957

@@ -242,6 +250,40 @@ const useInboxActions = (): IInboxActions => {
242250
});
243251
}
244252
},
253+
addTag: async (messageId, tag, fromWS) => {
254+
dispatch(addTag(messageId, tag));
255+
if (!fromWS) {
256+
await inboxClient.addTag(messageId, { tag });
257+
}
258+
259+
if (onEvent) {
260+
onEvent({
261+
event: "add-tag",
262+
message: allMessages.find((m) => m.messageId === messageId),
263+
messageId,
264+
data: {
265+
tag,
266+
},
267+
});
268+
}
269+
},
270+
removeTag: async (messageId, tag, fromWS) => {
271+
dispatch(removeTag(messageId, tag));
272+
if (!fromWS) {
273+
await inboxClient.removeTag(messageId, { tag });
274+
}
275+
276+
if (onEvent) {
277+
onEvent({
278+
event: "remove-tag",
279+
message: allMessages.find((m) => m.messageId === messageId),
280+
messageId,
281+
data: {
282+
tag,
283+
},
284+
});
285+
}
286+
},
245287
unpinMessage: async (messageId, fromWS) => {
246288
dispatch(unpinMessage(messageId));
247289
if (!fromWS) {

packages/react-provider/src/transports/types.ts

+1
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export interface IInboxMessagePreview {
3333
data?: Record<string, any>;
3434
/** ISO 8601 date the message was read */
3535
read?: string;
36+
tags?: string[];
3637
title?: string;
3738
trackingIds?: {
3839
openTrackingId?: string;

packages/react-provider/src/types.ts

+8-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ export type OnEvent = (eventParams: {
1818
messageId?: string;
1919
message?: IInboxMessagePreview;
2020
event: EventType;
21+
data?: Record<string, unknown>;
2122
}) => void;
2223

2324
export interface PinDetails {
@@ -64,13 +65,15 @@ export interface Brand {
6465
}
6566

6667
export type EventType =
67-
| "mark-all-read"
68-
| "read"
69-
| "unread"
68+
| "add-tag"
7069
| "archive"
71-
| "opened"
7270
| "click"
73-
| "unpin";
71+
| "mark-all-read"
72+
| "opened"
73+
| "read"
74+
| "remove-tag"
75+
| "unpin"
76+
| "unread";
7477

7578
export interface ThemeVariables {
7679
background?: string;

0 commit comments

Comments
 (0)