Published
Edited
Mar 29, 2021
Importers
Insert cell
Insert cell
Insert cell
Insert cell
/** Awaits for the Sign In, and stores the access once it arives **/
viewof conn = sfLoginForm(loginHost, {label:`Sign In to: ${loginHost}`});
// alternatively
// viewof conn = sfLoginForm(loginHost);
Insert cell
Insert cell
Insert cell
Insert cell
md `# Now that we've logged in, let's take a look at your org:

For the SObject: ${specialSObject}, it seems you have this many records: ${sObjectCount.totalSize}.

It looks like you also have ${specialFields.length} ${specialFieldType} fields:

<ul>
${specialFields.map(f => `<li>\`${specialSObject}.${f.name}[${f.type}] : ${f.label}\`</li>`).join('\n')}
</ul>

`
Insert cell
Insert cell
Insert cell
accountDescribe = await conn.describeSObject(specialSObject);
Insert cell
/** Standard Javascript filtering and sorting **/
specialFields = accountDescribe.fields
.filter(f => !specialFieldType || f.type === specialFieldType)
.sort((a, b) => a.label > b.label ? 1 : -1);
Insert cell
Insert cell
sObjectCount = await conn.query(`select count(id) objectCount from ${specialSObject}`);
Insert cell
Insert cell
Insert cell
/** Domain of the Heroku App we will use to login **/
viewof loginHost = Text({ label: 'Login Heroku App Domain', value: 'https://observable-oauth-salesforce.herokuapp.com' });
Insert cell
/** API Name of the SObject to describe **/
viewof specialSObject = submit({ label: 'API Name of SObject to describe', value: 'Account' });
Insert cell
/** The type of fields that we care about. Clear for all fields **/
viewof specialFieldType = submit({ label: 'Type of Field to Find', value: 'picklist' });
Insert cell
Insert cell
Insert cell
/**
* Creates a form that logs the user in, and returns a valid JsForce connection.
* @see https://jsforce.github.io
**/
sfLoginForm = function(loginHost, configurationOptions) {
const cleanConfigurationOptions = Object.assign({
label: `Sign in`
}, configurationOptions || {});
const {label} = cleanConfigurationOptions;
//-- show a button if not logged in.
const form = html `<form><button name="button">${label}</button></form>`;
/**
* Promise that completes when the user has finished oauth
**/
const signin = function() {
//-- the response we are waiting for must come from the login host and only login host.
const targetAddress = `${loginHost}/success`;
return new Promise((resolve, reject) => {
//-- open the login window in a new tab / browser
const popup = window.open(targetAddress, '_blank');
//-- postmessage handler (used for listening / removing the listener.
const message = (evt) => {
evt.preventDefault();
//-- troubleshoot postmessages
console.log('postmessage captured', evt.origin);
//-- ONLY continue if the origin is from the target host
if (evt.origin === loginHost) {
//-- capture the authentication info.
const sfoauth = evt.data.sfoauth;
//-- ONLY DIFFERENCE between sfUserForm and sfUserConnectionForm
const conn = new jsforce.Connection({
accessToken: sfoauth.access_token,
instanceUrl: sfoauth.instance_url
});
//-- close the popup
popup.close();
//-- stop listening for postmessages
removeEventListener('message', message);
//-- respolve the promise
resolve(conn);
}
};
//-- listen for postmessages
addEventListener('message', message);
});
}
//-- when the user clicks the button
form.button.onclick = async event => {
event.preventDefault();
try {
//-- run signin and wait for the response.
const sfoauth = await signin();
//-- store the authentication to .value on the item returned
form.value = sfoauth;
//-- change the contenxt to say it is signed in.
form.button.innerText = `signed in`;
} catch (err) {
form.value = null;
}
//-- let observable note the value has changed
form.dispatchEvent(new CustomEvent('input'));
};
//-- return the form, so it can use the `viewof` to store the value.
return form;
}
Insert cell
Insert cell
Insert cell
/** Library for using salesforce APIs.
* @see https://jsforce.github.io/
**/
jsforce = require('jsforce@1.10/build/jsforce.min.js');
Insert cell
/** Observable text input for easier configuration **/
import {
Text
} from "@observablehq/inputs"
Insert cell
/* import {submit} from "@mbostock/more-deliberate-inputs" */
submit = ({
value = "",
label = "",
placeholder = "Type here, then click submit.",
submit = "Submit",
...props
} = {}) => {
const form = html`<form><label style='font-size: 0.8em;'>${label} : </label><input name="text"> <button>${document.createTextNode(submit)}`;
Object.assign(form.text, props);
form.text.value = form.value = value;
form.text.placeholder = placeholder;
form.text.addEventListener("input", event => event.stopPropagation());
form.addEventListener("submit", event => {
form.value = form.text.value;
form.dispatchEvent(new CustomEvent("input"));
event.preventDefault();
});
return form;
}
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more