Skip to content

Commit c0efbce

Browse files
committed
new components
1 parent 00c76d5 commit c0efbce

File tree

19 files changed

+766
-264
lines changed

19 files changed

+766
-264
lines changed

components/salesforce_rest_api/actions/get-case/get-case.mjs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ export default {
44
key: "salesforce_rest_api-get-case",
55
name: "Get Case",
66
description: "Retrieves a case by its ID. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_get_field_values.htm)",
7-
//version: "0.0.1",
8-
version: "0.0.{{ts}}",
7+
version: "0.0.1",
98
type: "action",
109
props: {
1110
salesforce,

components/salesforce_rest_api/actions/list-email-messages/list-email-messages.mjs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@ export default {
1818
],
1919
label: "Case ID",
2020
description: "The ID of the case to retrieve email messages for",
21+
optional: true,
2122
},
2223
},
2324
async run({ $ }) {
2425
const fields = (await this.salesforce.getFieldsForObjectType("EmailMessage")).map(({ name }) => name);
25-
let query = `SELECT ${fields.join(", ")} FROM EmailMessage WHERE RelatedToId = '${this.caseId}'`;
26+
let query = `SELECT ${fields.join(", ")} FROM EmailMessage`;
27+
if (this.caseId) {
28+
query += ` WHERE RelatedToId = '${this.caseId}'`;
29+
}
2630

2731
const { records } = await this.salesforce.query({
2832
$,
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import salesforce from "../../salesforce_rest_api.app.mjs";
2+
3+
export default {
4+
key: "salesforce_rest_api-list-email-templates",
5+
name: "List Email Templates",
6+
description: "Lists all email templates. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_emailtemplate.htm)",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
salesforce,
11+
},
12+
async run({ $ }) {
13+
const fields = (await this.salesforce.getFieldsForObjectType("EmailTemplate")).map(({ name }) => name);
14+
const query = `SELECT ${fields.join(", ")} FROM EmailTemplate`;
15+
16+
const { records } = await this.salesforce.query({
17+
$,
18+
query,
19+
});
20+
$.export("$summary", `Sucessfully retrieved ${records.length} email templates`);
21+
return records;
22+
},
23+
};
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import salesforce from "../../salesforce_rest_api.app.mjs";
2+
3+
export default {
4+
key: "salesforce_rest_api-list-knowledge-articles",
5+
name: "List Knowledge Articles",
6+
description: "Lists all knowledge articles. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_knowledgearticle.htm)",
7+
version: "0.0.1",
8+
type: "action",
9+
props: {
10+
salesforce,
11+
},
12+
async run({ $ }) {
13+
const fields = (await this.salesforce.getFieldsForObjectType("KnowledgeArticle")).map(({ name }) => name);
14+
const query = `SELECT ${fields.join(", ")} FROM KnowledgeArticle`;
15+
16+
const { records } = await this.salesforce.query({
17+
$,
18+
query,
19+
});
20+
$.export("$summary", `Sucessfully retrieved ${records.length} knowledge articles`);
21+
return records;
22+
},
23+
};

components/salesforce_rest_api/actions/send-email/send-email.mjs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ export default {
44
key: "salesforce_rest_api-send-email",
55
name: "Send Email",
66
description: "Sends an email. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_action.meta/api_action/actions_obj_email_simple.htm)",
7-
version: "0.0.{{ts}}",
7+
version: "0.0.1",
88
type: "action",
99
props: {
1010
salesforce,
@@ -23,6 +23,12 @@ export default {
2323
label: "Body",
2424
description: "The body of the email",
2525
},
26+
logEmailOnSend: {
27+
type: "boolean",
28+
label: "Log Email on Send",
29+
description: "Indicates whether to log the email on the specified records’ activity time lines",
30+
optional: true,
31+
},
2632
},
2733
methods: {
2834
sendEmail(opts = {}) {
@@ -43,6 +49,7 @@ export default {
4349
emailSubject: this.emailSubject,
4450
emailBody: this.emailBody,
4551
senderType: "CurrentUser",
52+
logEmailOnSend: this.logEmailOnSend,
4653
},
4754
],
4855
},
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import {
2+
convertFieldsToProps, getAdditionalFields,
3+
} from "../../common/props-utils.mjs";
4+
import salesforce from "../../salesforce_rest_api.app.mjs";
5+
import { additionalFields } from "../common/base-create-update.mjs";
6+
7+
export default {
8+
key: "salesforce_rest_api-update-email-template",
9+
name: "Update Email Template",
10+
description: "Updates an email template. [See the documentation](https://developer.salesforce.com/docs/atlas.en-us.api_rest.meta/api_rest/dome_update_fields.htm)",
11+
version: "0.0.1",
12+
type: "action",
13+
props: {
14+
salesforce,
15+
recordId: {
16+
propDefinition: [
17+
salesforce,
18+
"recordId",
19+
() => ({
20+
objType: "EmailTemplate",
21+
}),
22+
],
23+
description: "The email template to update.",
24+
},
25+
fieldsToUpdate: {
26+
propDefinition: [
27+
salesforce,
28+
"fieldsToUpdate",
29+
() => ({
30+
objType: "EmailTemplate",
31+
}),
32+
],
33+
reloadProps: true,
34+
},
35+
},
36+
methods: {
37+
getAdditionalFields,
38+
convertFieldsToProps,
39+
},
40+
async additionalProps() {
41+
const { fieldsToUpdate } = this;
42+
const fields = await this.salesforce.getFieldsForObjectType("EmailTemplate");
43+
44+
const selectedFields = fields.filter(({ name }) => fieldsToUpdate.includes(name));
45+
const selectedFieldProps = this.convertFieldsToProps(selectedFields);
46+
47+
return {
48+
docsInfo: {
49+
type: "alert",
50+
alertType: "info",
51+
content: "[See the documentation](https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_emailtemplate.htm) for information on all available fields.",
52+
},
53+
...selectedFieldProps,
54+
additionalFields,
55+
};
56+
},
57+
async run({ $ }) {
58+
/* eslint-disable no-unused-vars */
59+
const {
60+
salesforce,
61+
recordId,
62+
fieldsToUpdate,
63+
getAdditionalFields: getData,
64+
convertFieldsToProps,
65+
docsInfo,
66+
additionalFields,
67+
...data
68+
} = this;
69+
/* eslint-enable no-unused-vars */
70+
const response = await this.salesforce.updateRecord("EmailTemplate", {
71+
$,
72+
id: recordId,
73+
data: {
74+
...data,
75+
...getData(),
76+
},
77+
});
78+
$.export("$summary", `Successfully updated Email Template record (ID: ${recordId})`);
79+
return response;
80+
},
81+
};
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import common from "../common/common-updated-record.mjs";
2+
import { DEFAULT_POLLING_SOURCE_TIMER_INTERVAL } from "@pipedream/platform";
3+
4+
export default {
5+
...common,
6+
type: "source",
7+
name: "Case Updated (Instant, of Selectable Type)",
8+
key: "salesforce_rest_api-case-updated-instant",
9+
description: "Emit new event when a case is updated. [See the documentation](https://sforce.co/3yPSJZy)",
10+
version: "0.0.1",
11+
props: {
12+
salesforce: common.props.salesforce,
13+
db: "$.service.db",
14+
http: {
15+
type: "$.interface.http",
16+
customResponse: true,
17+
},
18+
timer: {
19+
type: "$.interface.timer",
20+
description: "The timer is only used as a fallback if instant event delivery (webhook) is not available.",
21+
default: {
22+
intervalSeconds: DEFAULT_POLLING_SOURCE_TIMER_INTERVAL,
23+
},
24+
},
25+
fieldsToObtain: {
26+
propDefinition: [
27+
common.props.salesforce,
28+
"fieldsToObtain",
29+
() => ({
30+
objType: "Case",
31+
}),
32+
],
33+
optional: true,
34+
description: "Select the field(s) to be retrieved for the records. Only applicable if the source is running on a timer. If running on a webhook, or if not specified, all fields will be retrieved.",
35+
},
36+
},
37+
methods: {
38+
...common.methods,
39+
getObjectType() {
40+
return "Case";
41+
},
42+
},
43+
};
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import startCase from "lodash/startCase.js";
2+
import { v4 as uuidv4 } from "uuid";
3+
import common from "../common/common.mjs";
4+
5+
export default {
6+
...common,
7+
hooks: {
8+
...common.hooks,
9+
async deploy() {
10+
const objectType = this.getObjectType();
11+
const nameField = await this.salesforce.getNameFieldForObjectType(objectType);
12+
this.setNameField(nameField);
13+
14+
// emit historical events
15+
const { recentItems } = await this.salesforce.listSObjectTypeIds(objectType);
16+
const ids = recentItems.map((item) => item.Id);
17+
for (const id of ids.slice(-25)) {
18+
const object = await this.salesforce.getSObject(objectType, id);
19+
const event = {
20+
body: {
21+
"New": object,
22+
"UserId": id,
23+
},
24+
};
25+
this.processWebhookEvent(event);
26+
}
27+
},
28+
async activate() {
29+
// Attempt to create the webhook
30+
const secretToken = uuidv4();
31+
let webhookData;
32+
const objectType = this.getObjectType();
33+
try {
34+
webhookData = await this.createWebhook({
35+
endpointUrl: this.http.endpoint,
36+
sObjectType: objectType,
37+
event: this.getEventType(),
38+
secretToken,
39+
fieldsToCheck: this.getFieldsToCheck(),
40+
fieldsToCheckMode: this.getFieldsToCheckMode(),
41+
skipValidation: true, // neccessary for custom objects
42+
});
43+
console.log("Webhook created successfully");
44+
} catch (err) {
45+
console.log("Error creating webhook:", err);
46+
console.log("The source will operate on the polling schedule instead.");
47+
48+
const latestDateCovered = this.getLatestDateCovered();
49+
if (!latestDateCovered) {
50+
const now = new Date().toISOString();
51+
this.setLatestDateCovered(now);
52+
}
53+
54+
await this.timerActivateHook?.();
55+
}
56+
this._setSecretToken(secretToken);
57+
this._setWebhookData(webhookData);
58+
59+
const nameField = await this.salesforce.getNameFieldForObjectType(objectType);
60+
this.setNameField(nameField);
61+
},
62+
},
63+
methods: {
64+
...common.methods,
65+
generateTimerMeta(item, fieldName) {
66+
const { objectType } = this;
67+
const {
68+
CreatedDate: createdDate,
69+
[fieldName]: name,
70+
Id: id,
71+
} = item;
72+
const entityType = startCase(objectType);
73+
const summary = `New ${entityType} created: ${name ?? id}`;
74+
const ts = Date.parse(createdDate);
75+
return {
76+
id,
77+
summary,
78+
ts,
79+
};
80+
},
81+
generateWebhookMeta(data) {
82+
const nameField = this.getNameField();
83+
const { New: newObject } = data.body;
84+
const {
85+
CreatedDate: createdDate,
86+
Id: id,
87+
[nameField]: name,
88+
} = newObject;
89+
const summary = `New ${this.getObjectType()} created: ${name ?? id}`;
90+
const ts = Date.parse(createdDate);
91+
return {
92+
id,
93+
summary,
94+
ts,
95+
};
96+
},
97+
getEventType() {
98+
return "new";
99+
},
100+
async processTimerEvent(eventData) {
101+
const {
102+
paginate,
103+
setLatestDateCovered,
104+
getObjectTypeColumns,
105+
getNameField,
106+
generateTimerMeta,
107+
$emit: emit,
108+
} = this;
109+
110+
const {
111+
startTimestamp,
112+
endTimestamp,
113+
} = eventData;
114+
115+
const fieldName = getNameField();
116+
const columns = getObjectTypeColumns();
117+
118+
const events = await paginate({
119+
objectType: this.getObjectType(),
120+
startTimestamp,
121+
endTimestamp,
122+
columns,
123+
});
124+
125+
const [
126+
latestEvent,
127+
] = events;
128+
129+
if (latestEvent?.CreatedDate) {
130+
const latestDateCovered = new Date(latestEvent.CreatedDate);
131+
latestDateCovered.setSeconds(0);
132+
setLatestDateCovered(latestDateCovered.toISOString());
133+
}
134+
135+
Array.from(events)
136+
.reverse()
137+
.forEach((item) => {
138+
const meta = generateTimerMeta(item, fieldName);
139+
emit(item, meta);
140+
});
141+
},
142+
async timerActivateHook() {
143+
const {
144+
getObjectTypeDescription,
145+
setObjectTypeColumns,
146+
} = this;
147+
148+
let columns = this.fieldsToObtain;
149+
if (!columns?.length) {
150+
const { fields } = await getObjectTypeDescription(this.getObjectType());
151+
columns = fields.map(({ name }) => name);
152+
}
153+
154+
setObjectTypeColumns(columns);
155+
},
156+
},
157+
};

0 commit comments

Comments
 (0)