@pipedream/trello 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/actions/add-attachment-to-card/add-attachment-to-card.mjs +34 -27
  2. package/actions/add-checklist/add-checklist.mjs +9 -19
  3. package/actions/add-comment/add-comment.mjs +4 -5
  4. package/actions/add-existing-label-to-card/add-existing-label-to-card.mjs +9 -19
  5. package/actions/add-member-to-card/add-member-to-card.mjs +9 -19
  6. package/actions/archive-card/archive-card.mjs +5 -6
  7. package/actions/{common.mjs → common/common.mjs} +1 -1
  8. package/actions/complete-checklist-item/complete-checklist-item.mjs +4 -14
  9. package/actions/create-board/create-board.mjs +10 -47
  10. package/actions/create-card/create-card.mjs +52 -47
  11. package/actions/create-checklist-item/create-checklist-item.mjs +4 -14
  12. package/actions/create-label/create-label.mjs +5 -18
  13. package/actions/create-list/create-list.mjs +4 -12
  14. package/actions/delete-checklist/delete-checklist.mjs +8 -18
  15. package/actions/find-labels/find-labels.mjs +2 -3
  16. package/actions/find-list/find-list.mjs +2 -2
  17. package/actions/get-card/get-card.mjs +2 -2
  18. package/actions/get-list/get-list.mjs +1 -1
  19. package/actions/move-card-to-list/move-card-to-list.mjs +2 -2
  20. package/actions/remove-label-from-card/remove-label-from-card.mjs +9 -18
  21. package/actions/rename-list/rename-list.mjs +2 -2
  22. package/actions/search-boards/search-boards.mjs +10 -8
  23. package/actions/search-cards/search-cards.mjs +11 -8
  24. package/actions/search-checklists/search-checklists.mjs +56 -75
  25. package/actions/search-members/search-members.mjs +13 -23
  26. package/actions/update-card/update-card.mjs +22 -21
  27. package/common/constants.mjs +128 -0
  28. package/common/fields.mjs +1 -0
  29. package/package.json +2 -1
  30. package/sources/card-archived/card-archived.mjs +16 -28
  31. package/sources/card-archived/test-event.mjs +64 -0
  32. package/sources/card-due-date-reminder/card-due-date-reminder.mjs +111 -33
  33. package/sources/card-due-date-reminder/test-event.mjs +75 -0
  34. package/sources/card-moved/card-moved.mjs +20 -23
  35. package/sources/card-moved/test-event.mjs +78 -0
  36. package/sources/card-updates/card-updates.mjs +20 -27
  37. package/sources/card-updates/test-event.mjs +86 -0
  38. package/sources/common/actions.mjs +206 -0
  39. package/sources/common/common-board-based.mjs +12 -7
  40. package/sources/common/common-webhook.mjs +27 -16
  41. package/sources/common/common.mjs +5 -2
  42. package/sources/custom-webhook-events/custom-webhook-events.mjs +17 -48
  43. package/sources/new-activity/new-activity.mjs +22 -31
  44. package/sources/new-attachment/new-attachment.mjs +40 -49
  45. package/sources/new-attachment/test-event.mjs +69 -0
  46. package/sources/new-board/new-board.mjs +18 -11
  47. package/sources/new-board/test-event.mjs +100 -0
  48. package/sources/new-card/new-card.mjs +20 -27
  49. package/sources/new-card/test-event.mjs +79 -0
  50. package/sources/new-checklist/new-checklist.mjs +39 -22
  51. package/sources/new-checklist/test-event.mjs +22 -0
  52. package/sources/new-comment-added-to-card/new-comment-added-to-card.mjs +38 -44
  53. package/sources/new-comment-added-to-card/test-event.mjs +298 -0
  54. package/sources/new-label/new-label.mjs +13 -14
  55. package/sources/new-label/test-event.mjs +7 -0
  56. package/sources/new-label-added-to-card/new-label-added-to-card.mjs +23 -24
  57. package/sources/new-label-added-to-card/test-event.mjs +85 -0
  58. package/sources/new-member-on-card/new-member-on-card.mjs +17 -26
  59. package/sources/new-member-on-card/test-event.mjs +83 -0
  60. package/sources/new-notification/new-notification.mjs +3 -12
  61. package/trello.app.mjs +211 -33
  62. package/actions/close-board/close-board.mjs +0 -31
  63. package/actions/create-checklist/create-checklist.mjs +0 -78
  64. package/actions/create-comment-on-card/create-comment-on-card.mjs +0 -59
  65. package/sources/new-list/new-list.mjs +0 -33
@@ -0,0 +1,86 @@
1
+ export default {
2
+ "id": "620eb14ebda9570d72fddead",
3
+ "badges": {
4
+ "attachmentsByType": {
5
+ "trello": {
6
+ "board": 0,
7
+ "card": 0
8
+ }
9
+ },
10
+ "externalSource": null,
11
+ "location": false,
12
+ "votes": 0,
13
+ "viewingMemberVoted": false,
14
+ "subscribed": false,
15
+ "fogbugz": "",
16
+ "checkItems": 1,
17
+ "checkItemsChecked": 1,
18
+ "checkItemsEarliestDue": null,
19
+ "comments": 3,
20
+ "attachments": 1,
21
+ "description": false,
22
+ "due": "2021-05-10T21:50:00.000Z",
23
+ "dueComplete": false,
24
+ "start": null,
25
+ "lastUpdatedByAi": false
26
+ },
27
+ "checkItemStates": [
28
+ {
29
+ "idCheckItem": "620eb14fbda9570d72fde031",
30
+ "state": "complete"
31
+ }
32
+ ],
33
+ "closed": false,
34
+ "dueComplete": false,
35
+ "dateLastActivity": "2024-09-30T16:31:35.215Z",
36
+ "desc": "",
37
+ "descData": {
38
+ "emoji": {}
39
+ },
40
+ "due": "2021-05-10T21:50:00.000Z",
41
+ "dueReminder": null,
42
+ "email": null,
43
+ "idBoard": "5f4d7be6c45c22583f75fa02",
44
+ "idChecklists": [
45
+ "620eb14fbda9570d72fde030"
46
+ ],
47
+ "idList": "5f4d7f78bdd7ce4d2d25fdda",
48
+ "idMembers": [],
49
+ "idMembersVoted": [],
50
+ "idShort": 85,
51
+ "idAttachmentCover": "620eb14ebda9570d72fdded7",
52
+ "labels": [
53
+ {
54
+ "id": "5f4d7be6cdabcf46c027c792",
55
+ "idBoard": "5f4d7be6c45c22583f75fa02",
56
+ "idOrganization": "6047c17c2f558003144e04d7",
57
+ "name": "green label",
58
+ "nodeId": "ari:cloud:trello::label/workspace/6047c17c2f558003144e04d7/5f4d7be6cdabcf46c027c792",
59
+ "color": "green",
60
+ "uses": 9
61
+ },
62
+ ],
63
+ "idLabels": [
64
+ "5f4d7be6cdabcf46c027c792",
65
+ ],
66
+ "manualCoverAttachment": false,
67
+ "name": "new card",
68
+ "pinned": false,
69
+ "pos": 360447,
70
+ "shortLink": "dho6bOdR",
71
+ "shortUrl": "https://trello.com/c/dho6bOdR",
72
+ "start": null,
73
+ "subscribed": false,
74
+ "url": "https://trello.com/c/dho6bOdR/85-new-card",
75
+ "cover": {
76
+ "idAttachment": "620eb14ebda9570d72fdded7",
77
+ "color": null,
78
+ "idUploadedBackground": null,
79
+ "size": "normal",
80
+ "brightness": "dark",
81
+ "idPlugin": null
82
+ },
83
+ "isTemplate": false,
84
+ "cardRole": null,
85
+ "customFieldItems": []
86
+ }
@@ -0,0 +1,206 @@
1
+ export default [
2
+ {
3
+ label: "Accept Enterprise Join Request",
4
+ value: "acceptEnterpriseJoinRequest",
5
+ },
6
+ {
7
+ label: "Add Attachment To Card",
8
+ value: "addAttachmentToCard",
9
+ },
10
+ {
11
+ label: "Add Checklist To Card",
12
+ value: "addChecklistToCard",
13
+ },
14
+ {
15
+ label: "Add Member To Board",
16
+ value: "addMemberToBoard",
17
+ },
18
+ {
19
+ label: "Add Member To Card",
20
+ value: "addMemberToCard",
21
+ },
22
+ {
23
+ label: "Add Member To Organization",
24
+ value: "addMemberToOrganization",
25
+ },
26
+ {
27
+ label: "Add Organization To Enterprise",
28
+ value: "addOrganizationToEnterprise",
29
+ },
30
+ {
31
+ label: "Add To Enterprise Plugin Whitelist",
32
+ value: "addToEnterprisePluginWhitelist",
33
+ },
34
+ {
35
+ label: "Add To Organization Board",
36
+ value: "addToOrganizationBoard",
37
+ },
38
+ {
39
+ label: "Comment Card",
40
+ value: "commentCard",
41
+ },
42
+ {
43
+ label: "Convert To Card From Check Item",
44
+ value: "convertToCardFromCheckItem",
45
+ },
46
+ {
47
+ label: "Copy Board",
48
+ value: "copyBoard",
49
+ },
50
+ {
51
+ label: "Copy Card",
52
+ value: "copyCard",
53
+ },
54
+ {
55
+ label: "Copy Comment Card",
56
+ value: "copyCommentCard",
57
+ },
58
+ {
59
+ label: "Create Board",
60
+ value: "createBoard",
61
+ },
62
+ {
63
+ label: "Create Card",
64
+ value: "createCard",
65
+ },
66
+ {
67
+ label: "Create List",
68
+ value: "createList",
69
+ },
70
+ {
71
+ label: "Create Organization",
72
+ value: "createOrganization",
73
+ },
74
+ {
75
+ label: "Delete Board Invitation",
76
+ value: "deleteBoardInvitation",
77
+ },
78
+ {
79
+ label: "Delete Card",
80
+ value: "deleteCard",
81
+ },
82
+ {
83
+ label: "Delete Organization Invitation",
84
+ value: "deleteOrganizationInvitation",
85
+ },
86
+ {
87
+ label: "Disable Enterprise Plugin Whitelist",
88
+ value: "disableEnterprisePluginWhitelist",
89
+ },
90
+ {
91
+ label: "Disable Plugin",
92
+ value: "disablePlugin",
93
+ },
94
+ {
95
+ label: "Disable Power Up",
96
+ value: "disablePowerUp",
97
+ },
98
+ {
99
+ label: "Email Card",
100
+ value: "emailCard",
101
+ },
102
+ {
103
+ label: "Enable Enterprise Plugin Whitelist",
104
+ value: "enableEnterprisePluginWhitelist",
105
+ },
106
+ {
107
+ label: "Enable Plugin",
108
+ value: "enablePlugin",
109
+ },
110
+ {
111
+ label: "Enable Power Up",
112
+ value: "enablePowerUp",
113
+ },
114
+ {
115
+ label: "Make Admin Of Board",
116
+ value: "makeAdminOfBoard",
117
+ },
118
+ {
119
+ label: "Make Normal Member Of Board",
120
+ value: "makeNormalMemberOfBoard",
121
+ },
122
+ {
123
+ label: "Make Normal Member Of Organization",
124
+ value: "makeNormalMemberOfOrganization",
125
+ },
126
+ {
127
+ label: "Make Observer Of Board",
128
+ value: "makeObserverOfBoard",
129
+ },
130
+ {
131
+ label: "Member Joined Trello",
132
+ value: "memberJoinedTrello",
133
+ },
134
+ {
135
+ label: "Move Card From Board",
136
+ value: "moveCardFromBoard",
137
+ },
138
+ {
139
+ label: "Move Card To Board",
140
+ value: "moveCardToBoard",
141
+ },
142
+ {
143
+ label: "Move List From Board",
144
+ value: "moveListFromBoard",
145
+ },
146
+ {
147
+ label: "Move List To Board",
148
+ value: "moveListToBoard",
149
+ },
150
+ {
151
+ label: "Remove Checklist From Card",
152
+ value: "removeChecklistFromCard",
153
+ },
154
+ {
155
+ label: "Remove From Enterprise Plugin Whitelist",
156
+ value: "removeFromEnterprisePluginWhitelist",
157
+ },
158
+ {
159
+ label: "Remove From Organization Board",
160
+ value: "removeFromOrganizationBoard",
161
+ },
162
+ {
163
+ label: "Remove Member From Card",
164
+ value: "removeMemberFromCard",
165
+ },
166
+ {
167
+ label: "Remove Organization From Enterprise",
168
+ value: "removeOrganizationFromEnterprise",
169
+ },
170
+ {
171
+ label: "Unconfirmed Board Invitation",
172
+ value: "unconfirmedBoardInvitation",
173
+ },
174
+ {
175
+ label: "Unconfirmed Organization Invitation",
176
+ value: "unconfirmedOrganizationInvitation",
177
+ },
178
+ {
179
+ label: "Update Board",
180
+ value: "updateBoard",
181
+ },
182
+ {
183
+ label: "Update Card",
184
+ value: "updateCard",
185
+ },
186
+ {
187
+ label: "Update Check Item State On Card",
188
+ value: "updateCheckItemStateOnCard",
189
+ },
190
+ {
191
+ label: "Update Checklist",
192
+ value: "updateChecklist",
193
+ },
194
+ {
195
+ label: "Update List",
196
+ value: "updateList",
197
+ },
198
+ {
199
+ label: "Update Member",
200
+ value: "updateMember",
201
+ },
202
+ {
203
+ label: "Update Organization",
204
+ value: "updateOrganization",
205
+ },
206
+ ];
@@ -14,7 +14,7 @@ export default {
14
14
  ],
15
15
  },
16
16
  onlyEventsRelatedWithAuthenticatedUser: {
17
- label: "Only Events Related With Me",
17
+ label: "Only Events Related To Me",
18
18
  description: "Only will emit events from the cards related with the authenticated user",
19
19
  type: "boolean",
20
20
  default: false,
@@ -32,19 +32,24 @@ export default {
32
32
  return false;
33
33
  }
34
34
 
35
+ if (this.lists?.length) {
36
+ const list = await this.app.getCardList({
37
+ cardId: result.idCard,
38
+ });
39
+ if (!this.lists.includes(list.id)) {
40
+ return false;
41
+ }
42
+ }
43
+
35
44
  const member = await this.app.getMember({
36
45
  memberId: "me",
37
46
  });
38
47
 
39
- if (
48
+ return !(
40
49
  this.onlyEventsRelatedWithAuthenticatedUser &&
41
50
  result?.idMembers?.length &&
42
51
  !result.idMembers.includes(member.id)
43
- ) {
44
- return false;
45
- }
46
-
47
- return true;
52
+ );
48
53
  },
49
54
  },
50
55
  };
@@ -9,12 +9,9 @@ export default {
9
9
  },
10
10
  hooks: {
11
11
  async deploy() {
12
- const {
13
- sampleEvents, sortField,
14
- } = await this.getSampleEvents();
15
- sampleEvents.sort((a, b) => (Date.parse(a[sortField]) > Date.parse(b[sortField]))
16
- ? 1
17
- : -1);
12
+ let sampleEvents = await this.getSampleEvents();
13
+ const sortField = this.getSortField();
14
+ sampleEvents = this.sortItemsByDate(sampleEvents, sortField);
18
15
  for (const event of sampleEvents.slice(-25)) {
19
16
  this.emitEvent(event);
20
17
  }
@@ -28,17 +25,25 @@ export default {
28
25
  callbackURL: this.http.endpoint,
29
26
  },
30
27
  });
31
- this.db.set("hookId", id);
28
+ this._setHookId(id);
32
29
  },
33
30
  async deactivate() {
34
- const hookId = this.db.get("hookId");
35
- await this.deleteHook({
36
- hookId,
37
- });
31
+ const hookId = this._getHookId();
32
+ if (hookId) {
33
+ await this.deleteHook({
34
+ hookId,
35
+ });
36
+ }
38
37
  },
39
38
  },
40
39
  methods: {
41
40
  ...common.methods,
41
+ _getHookId() {
42
+ return this.db.get("hookId");
43
+ },
44
+ _setHookId(hookId) {
45
+ this.db.set("hookId", hookId);
46
+ },
42
47
  getBase64Digest(data) {
43
48
  const { secret } = this.app.getToken();
44
49
  return createHmac("sha1", secret)
@@ -57,7 +62,6 @@ export default {
57
62
  createHook(args = {}) {
58
63
  return this.app.post({
59
64
  ...args,
60
- debug: true,
61
65
  path: "/webhooks/",
62
66
  });
63
67
  },
@@ -66,7 +70,6 @@ export default {
66
70
  } = {}) {
67
71
  return this.app.delete({
68
72
  ...args,
69
- debug: true,
70
73
  path: `/webhooks/${hookId}`,
71
74
  });
72
75
  },
@@ -97,9 +100,15 @@ export default {
97
100
  isRelevant() {
98
101
  return true;
99
102
  },
103
+ getResult(action) {
104
+ return action;
105
+ },
100
106
  getSampleEvents() {
101
107
  throw new Error("getSampleEvents not implemented");
102
108
  },
109
+ getSortField() {
110
+ throw new Error("getSortField is not implemented");
111
+ },
103
112
  },
104
113
  async run(event) {
105
114
  if (event.body === undefined) {
@@ -112,15 +121,17 @@ export default {
112
121
  return;
113
122
  }
114
123
 
115
- if (!this.isCorrectEventType(event)) {
124
+ const { action } = event.body;
125
+
126
+ if (!this.isCorrectEventType(action)) {
116
127
  console.log("The event is not of the correct type. Skipping...");
117
128
  return;
118
129
  }
119
130
 
120
- const result = await this.getResult(event);
131
+ const result = await this.getResult(action);
121
132
  const isRelevant = await this.isRelevant({
122
133
  result,
123
- event,
134
+ action,
124
135
  });
125
136
 
126
137
  if (!isRelevant) {
@@ -13,11 +13,11 @@ export default {
13
13
  * @param {string} name - The name of the item of the book.
14
14
  */
15
15
  generateMeta({
16
- id, name: summary,
16
+ id, name,
17
17
  }) {
18
18
  return {
19
19
  id,
20
- summary,
20
+ summary: name || `${id}`,
21
21
  ts: Date.now(),
22
22
  };
23
23
  },
@@ -30,5 +30,8 @@ export default {
30
30
  const meta = this.generateMeta(result);
31
31
  this.$emit(result, meta);
32
32
  },
33
+ sortItemsByDate(items, sortField) {
34
+ return items.sort((a, b) => (Date.parse(a[sortField]) > Date.parse(b[sortField])));
35
+ },
33
36
  },
34
37
  };
@@ -4,9 +4,9 @@ import events from "../common/events.mjs";
4
4
  export default {
5
5
  ...common,
6
6
  key: "trello-custom-webhook-events",
7
- name: "Custom Webhook Events (Instant)",
7
+ name: "Custom Webhook Events (Instant)", /* eslint-disable-line pipedream/source-name */
8
8
  description: "Emit new events for activity matching a board, event types, lists and/or cards.",
9
- version: "0.1.0",
9
+ version: "0.1.1",
10
10
  type: "source",
11
11
  props: {
12
12
  ...common.props,
@@ -42,59 +42,29 @@ export default {
42
42
  ],
43
43
  },
44
44
  },
45
- hooks: {
46
- ...common.hooks,
47
- async deploy() {
48
- const {
49
- sampleEvents, sortField,
50
- } = await this.getSampleEvents();
51
- sampleEvents.sort((a, b) => (Date.parse(a[sortField]) > Date.parse(b[sortField]))
52
- ? 1
53
- : -1);
54
- for (const action of sampleEvents.slice(-25)) {
55
- this.emitEvent({
56
- action,
57
- });
58
- }
59
- },
60
- },
61
45
  methods: {
62
46
  ...common.methods,
63
- getCardList({
64
- cardId, ...args
65
- } = {}) {
66
- return this.app._makeRequest({
67
- path: `/cards/${cardId}/list`,
68
- ...args,
69
- });
70
- },
71
- async getSampleEvents() {
72
- const eventTypes = this.eventTypes && this.eventTypes.length > 0
47
+ getSampleEvents() {
48
+ const eventTypes = this.eventTypes?.length
73
49
  ? this.eventTypes.join(",")
74
50
  : null;
75
- const actions = await this.app.getBoardActivity({
51
+ return this.app.getBoardActivity({
76
52
  boardId: this.board,
77
53
  params: {
78
54
  filter: eventTypes,
79
55
  },
80
56
  });
81
- return {
82
- sampleEvents: actions,
83
- sortField: "date",
84
- };
85
57
  },
86
- isCorrectEventType(event) {
87
- const eventType = event.body?.action?.type;
58
+ getSortField() {
59
+ return "date";
60
+ },
61
+ isCorrectEventType({ type }) {
88
62
  return (
89
- (eventType) &&
90
- (!this.eventTypes ||
91
- this.eventTypes.length === 0 ||
92
- this.eventTypes.includes(eventType))
63
+ (type) &&
64
+ (!this.eventTypes?.length ||
65
+ this.eventTypes.includes(type))
93
66
  );
94
67
  },
95
- async getResult(event) {
96
- return event.body;
97
- },
98
68
  async isRelevant({ result: body }) {
99
69
  let listId = body.action?.data?.list?.id;
100
70
  const cardId = body.action?.data?.card?.id;
@@ -106,22 +76,21 @@ export default {
106
76
  listId = res.id;
107
77
  }
108
78
  return (
109
- (!this.lists ||
110
- this.lists.length === 0 ||
79
+ (!this.lists?.length ||
111
80
  !listId ||
112
81
  this.lists.includes(listId)) &&
113
- (!this.cards || this.cards.length === 0 || !cardId || this.cards.includes(cardId))
82
+ (!this.cards?.length || !cardId || this.cards.includes(cardId))
114
83
  );
115
84
  },
116
- generateMeta({ action }) {
85
+ generateMeta(action) {
117
86
  const {
118
87
  id,
119
- type: summary,
88
+ type,
120
89
  date,
121
90
  } = action;
122
91
  return {
123
92
  id,
124
- summary,
93
+ summary: `New ${type} event`,
125
94
  ts: Date.parse(date),
126
95
  };
127
96
  },
@@ -1,11 +1,12 @@
1
1
  import common from "../common/common-webhook.mjs";
2
+ import actions from "../common/actions.mjs";
2
3
 
3
4
  export default {
4
5
  ...common,
5
6
  key: "trello-new-activity",
6
- name: "New Activity (Instant)",
7
+ name: "New Board Activity (Instant)",
7
8
  description: "Emit new event for new activity on a board.",
8
- version: "0.1.0",
9
+ version: "0.1.1",
9
10
  type: "source",
10
11
  props: {
11
12
  ...common.props,
@@ -15,50 +16,40 @@ export default {
15
16
  "board",
16
17
  ],
17
18
  },
18
- },
19
- hooks: {
20
- ...common.hooks,
21
- async deploy() {
22
- const {
23
- sampleEvents, sortField,
24
- } = await this.getSampleEvents();
25
- sampleEvents.sort((a, b) => (Date.parse(a[sortField]) > Date.parse(b[sortField]))
26
- ? 1
27
- : -1);
28
- for (const action of sampleEvents.slice(-25)) {
29
- this.emitEvent({
30
- action,
31
- });
32
- }
19
+ activityTypes: {
20
+ type: "string[]",
21
+ label: "Activity Types",
22
+ description: "Filter incoming events by the activity type",
23
+ options: actions,
24
+ optional: true,
33
25
  },
34
26
  },
35
27
  methods: {
36
28
  ...common.methods,
37
- async getSampleEvents() {
38
- const actions = await this.app.getBoardActivity({
29
+ getSampleEvents() {
30
+ return this.app.getBoardActivity({
39
31
  boardId: this.board,
40
32
  });
41
- return {
42
- sampleEvents: actions,
43
- sortField: "date",
44
- };
45
33
  },
46
- async getResult(event) {
47
- return event.body;
34
+ getSortField() {
35
+ return "date";
48
36
  },
49
- isRelevant({ event }) {
50
- const boardId = event.body?.action?.data?.board?.id;
51
- return !this.board || this.board === boardId;
37
+ isRelevant({ action }) {
38
+ const {
39
+ data, type,
40
+ } = action;
41
+ return ((!this.board || this.board === data?.board?.id)
42
+ && (!this.activityTypes?.length || this.activityTypes.includes(type)));
52
43
  },
53
- generateMeta({ action }) {
44
+ generateMeta(action) {
54
45
  const {
55
46
  id,
56
- type: summary,
47
+ type,
57
48
  date,
58
49
  } = action;
59
50
  return {
60
51
  id,
61
- summary,
52
+ summary: `New ${type} activity`,
62
53
  ts: Date.parse(date),
63
54
  };
64
55
  },