Skip to content

Commit 35e1471

Browse files
authored
Stop replacing consecutive spaces (#5)
Add example script for data transfer
1 parent e06f9a9 commit 35e1471

File tree

5 files changed

+138
-21
lines changed

5 files changed

+138
-21
lines changed

force-app/main/default/classes/APICallController.cls

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,17 @@
11
/**
2-
** description: Controller for making api calls and sending the response back
2+
* description: Controller for making api calls and sending the response back
33
**/
44

55
public with sharing class APICallController {
6+
/**
7+
* description Given an endpoint, request params and headers, callout the api and return the response
8+
* @param endpoint The endpoint to callout to
9+
* @param method The http method to use
10+
* @param bodyStr The request body string.
11+
* @param headers Map of string key and value for request headers
12+
* @return HttpResponseWrapper
13+
*
14+
*/
615
@AuraEnabled
716
public static HttpResponseWrapper makeApiCall(
817
String endPoint,

force-app/main/default/classes/DynamicSOQLDMLController.cls

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,52 @@
11
public with sharing class DynamicSOQLDMLController {
2+
/**
3+
* Execute a Soql Query
4+
* @param query The soql query to execute
5+
*
6+
* @return SObject[]
7+
**/
28
@AuraEnabled
39
public static SObject[] executeSoqlQuery(String query) {
410
return Database.query(query);
511
}
612

13+
/**
14+
* Get JavaScript from a Custom Metadata with a given name
15+
* @param cmdtName The name of Custom Metadata record to fetch the script from
16+
*
17+
* @return String
18+
**/
719
@AuraEnabled(cacheable=true)
820
public static String getJSFromCmdt(String cmdtName) {
9-
JS_Button__mdt[] jsButton = [
10-
SELECT Script__c
11-
FROM JS_Button__mdt
12-
WHERE DeveloperName = :cmdtName
13-
LIMIT 1
14-
];
21+
JS_Button__mdt[] jsButton = [SELECT Script__c FROM JS_Button__mdt WHERE DeveloperName = :cmdtName LIMIT 1];
1522
if (jsButton.size() == 1)
1623
return jsButton[0].Script__c;
1724
else
1825
return '';
1926
}
2027

28+
/**
29+
* Short Description
30+
* @param recordId Get the SObject Type given a record Id
31+
*
32+
* @return String
33+
**/
2134
@AuraEnabled(cacheable=true)
2235
public static String getSObjectTypeFromId(Id recordId) {
2336
return recordId.getSObjectType().getDescribe().getName();
2437
}
2538

39+
/**
40+
* Execute a DML statement
41+
* @param operation 'Insert','Update' or 'Upsert'
42+
* @param strdata The records to update, stringified
43+
* @param sobjectType The SObject type to perform the DML on
44+
*
45+
* @return Id[]
46+
**/
2647
@AuraEnabled
27-
public static Id[] executeDml(
28-
String operation,
29-
String strData,
30-
String sObjectType
31-
) {
32-
SObject[] records = (SObject[]) JSON.deserialize(
33-
strData,
34-
Type.forName('List<' + sObjectType + '>')
35-
);
48+
public static Id[] executeDml(String operation, String strData, String sObjectType) {
49+
SObject[] records = (SObject[]) JSON.deserialize(strData, Type.forName('List<' + sObjectType + '>'));
3650
if (operation == 'insert') {
3751
insert records;
3852
return new List<Id>(new Map<Id, SObject>(records).keySet());

force-app/main/default/customMetadata/JS_Button.Account.md-meta.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
<field>Script__c</field>
77
<value xsi:type="xsd:string">let acct = || Select NumberOfEmployees from Account where Id=&apos;${recordId}&apos; ||;
88

9-
109
acct[0].NumberOfEmployees = (acct[0].NumberOfEmployees || 0) + 10;
1110

1211
let acctId = || update acct ||;

force-app/main/default/lwc/jsButtonLwc/jsButtonLwc.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@ import getSObjectType from "@salesforce/apex/DynamicSOQLDMLController.getSObject
66
import { ShowToastEvent } from "lightning/platformShowToastEvent";
77
import HttpRequest from "c/httpRequest";
88

9-
const REGEX_SOQL = "\\|\\|\\s?(select\\s+[^|]+)\\s?\\|\\|";
10-
const REGEX_UPDATE = "\\|\\|\\s?update\\s([^|;]+);?\\s*\\|\\|";
9+
const REGEX_SOQL = "\\|\\|\\s+(select\\s+[^|]+)\\s+\\|\\|";
10+
const REGEX_UPDATE = "\\|\\|\\s+update\\s+([\\w\\d_]+).*\\|\\|";
1111
const REGEX_INSERT_UPSERT =
12-
"\\|\\|\\s?(insert|upsert)\\s([\\w\\d_]+)\\s?\\(\\s?(\\w+).*\\|\\|";
12+
"\\|\\|\\s*(insert|upsert)\\s+([\\w\\d_]+)\\s*\\(\\s*(\\w+).*\\|\\|";
1313

1414
export default class JsButtonLwc extends LightningElement {
1515
@api js;
@@ -77,7 +77,8 @@ export default class JsButtonLwc extends LightningElement {
7777

7878
async runJS(js) {
7979
//replace consecutive spaces
80-
js = js.replace(/\s+/g, " ");
80+
//don't replace consecutive spaces
81+
//js = js.replace(/\s+/g, " ");
8182

8283
//parse soql
8384
js = js.replace(
@@ -96,6 +97,7 @@ export default class JsButtonLwc extends LightningElement {
9697
new RegExp(REGEX_INSERT_UPSERT, "gi"),
9798
"await this.executeDml('$1',$3,'$2');"
9899
);
100+
//eslint-disable-next-line
99101
let op = await Function("recordId", `return (async ()=>{${js}})()`).bind(
100102
this
101103
)(this.recordId);

scripts/jsButton/copyData.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/***
2+
* This script moves Account, Contact and Opportunity data from a source instance to the current SF instance.
3+
* The source instance is expected to be configured using a named credential named 'source'
4+
*/
5+
let baseurl = "callout:source/services/data/v48.0/query?q=";
6+
this.httpRequest.setEndpoint(baseurl + "Select+Id,Name+from+Account");
7+
this.httpRequest.addHeader("Accept", "application/json");
8+
let resp = await this.httpRequest.send();
9+
resp = JSON.parse(resp.body);
10+
11+
if (!resp.done) {
12+
alert("Request to fetch Accounts failed");
13+
}
14+
let accts = resp.records;
15+
this.httpRequest.setEndpoint(
16+
baseurl + "Select+Id,LastName,FirstName,Email,AccountId+from+Contact"
17+
);
18+
resp = await this.httpRequest.send();
19+
resp = JSON.parse(resp.body);
20+
if (!resp.done) {
21+
alert("Request to fetch Contacts failed");
22+
}
23+
let contacts = resp.records;
24+
25+
this.httpRequest.setEndpoint(
26+
baseurl +
27+
"Select+Id,Name,CloseDate,StageName,AccountId,ContactId+from+Opportunity"
28+
);
29+
resp = await this.httpRequest.send();
30+
resp = JSON.parse(resp.body);
31+
if (!resp.done) {
32+
alert("Request to fetch Opportunities failed");
33+
}
34+
let opps = resp.records;
35+
36+
let acctsToInsert = accts.map((a) => {
37+
let b = { ...a };
38+
delete b.Id;
39+
delete b.attributes;
40+
return b;
41+
});
42+
43+
let newAcctIds=[];
44+
try{
45+
newAcctIds = || insert Account(acctsToInsert) ||;
46+
}catch(err){
47+
alert(JSON.stringify(err));
48+
}
49+
let acctIdMap = accts.reduce(
50+
(obj, a, i) => ({ ...obj, [a.Id]: newAcctIds[i] }),
51+
{}
52+
);
53+
54+
let contactsToInsert = contacts
55+
.map((c) => {
56+
let d = { ...c, AccountId: acctIdMap[c.AccountId] };
57+
delete d.Id;
58+
delete d.attributes;
59+
return d;
60+
})
61+
.filter((c) => c.AccountId);
62+
63+
let newCtctIds = [];
64+
try {
65+
newCtctIds = || insert Contact(contactsToInsert) ||;
66+
} catch (err) {
67+
alert(JSON.stringify(err));
68+
}
69+
let ctctIdMap = contacts.reduce(
70+
(obj, c, i) => ({ ...obj, [c.Id]: newCtctIds[i] }),
71+
{}
72+
);
73+
74+
let oppsToInsert = opps
75+
.map((o) => {
76+
let p = {
77+
...o,
78+
AccountId: acctIdMap[o.AccountId],
79+
ContactId: ctctIdMap[o.ContactId]
80+
};
81+
delete p.Id;
82+
delete p.attributes;
83+
return p;
84+
})
85+
.filter((o) => o.AccountId);
86+
87+
let newOppIds = [];
88+
try {
89+
newOppIds = || insert Opportunity(oppsToInsert) ||;
90+
} catch (err) {
91+
alert(JSON.stringify(err));
92+
}
93+
alert('Data transfer complete');

0 commit comments

Comments
 (0)