Building a Slack App with Native SFDC Integration
Tags: slack, integration, webdev, tutorial
Published: 2022-04-05 13:38:35

### Building a Slack App: Designing a UI

This post is a continuation of our series based on [a video series explaining how to build Slack Apps](https://www.youtube.com/playlist?list=PLgIMQe2PKPSKcl26YQoKCR7F3CwIc8kxi) that integrate with Salesforce APIs. With the [Slack Starter Kit](https://github.com/developerforce/salesforce-slack-starter-kit) from Salesforce, Slack app developers can offload common concerns like Salesforce authentication, directory hierarchies, reusable code, and deployments to Heroku. The end result is less time spent wrangling code and more time building features for your app.

[In our last post](https://dev.to/salesforcedevs/building-a-slack-app-with-native-sfdc-integration-o94), we familiarized ourselves with the starter kit and set up our development environment to build a basic Slack app. In this post, we’ll continue building on that Slack app, focusing on how the Slack Starter Kit makes it easy to develop two essential components of every Slack app:

1. Listening for user interactions
2. Drawing a user interface.


### Responding to events

If you’ve ever developed a front-end web app using JavaScript or CSS, you’re probably familiar with the basic tenets of event handling. Events in this context are defined as the actions a user takes on your website. For example, a mouse pointer clicking on a link emits an `onclick` event; a pointer linking over a piece of text emits `onhover`; a keyboard keystroke emits `onkeypressed`; and so on.


![Photo by [Stephen Phillips - Hostreviews.co.uk](https://unsplash.com/@hostreviews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on[ Unsplash](https://unsplash.com/s/photos/slack?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ahqj3m9moouphx6lbvfp.jpg)

Photo by [Stephen Phillips - Hostreviews.co.uk](https://unsplash.com/@hostreviews?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on[ Unsplash](https://unsplash.com/s/photos/slack?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)

In Slack, there’s a [multitude of events](https://api.slack.com/interactivity/handling) you can listen to, ranging from individual events (when a message is posted or pinned) to global changes (when channel names or visibilities are changed) to the administrative (when an app is installed or a new emoji is uploaded). [The full list of emitted events](https://api.slack.com/events?filter=Events) is truly impressive. The process for listening to an event is as follows:


* First, your app needs to define a webhook URL. This is a path on your server which can receive POST requests from Slack.
* Next, in your App Manifest, you identify the events which you’d like to capture.
* When an event occurs in a workspace where your app is installed, a JSON payload is sent to your app. Every event has its own unique payload.

When your app receives the event from Slack, you can do anything you want: respond to the user, pop open a dialog to ask for more information, or simply store some information away in your database. There’s only one important point to remember: [you must respond to Slack within three seconds](https://api.slack.com/interactivity/handling#acknowledgment_response). This is to let Slack know that your app received its payload and is working on a response. You can do that work in the background—perhaps on a different thread, taking as long as you need—but only after you let Slack know everything is `200 OK`.

Let’s take a look at how event handling works in practice. Head on over to your App Manifest, and scroll down to the bottom of the page, near the `settings` key. It should look like this: 


```
settings:
  event_subscriptions:
    request_url: https://<your-app-name>.herokuapp.com/slack/events
    bot_events:
      - app_home_opened
  interactivity:
    is_enabled: true
    request_url: https://<your-app-name>.herokuapp.com/slack/events
```


This section identifies where Slack should send its payload once an event occurs. The `bot_events` key already defines one event to listen to, [app_home_opened](https://api.slack.com/events/app_home_opened), which is triggered once your app is opened in Slack.

Now, open up the local copy of your Starter Kit in your IDE; navigate to `apps/slack-salesforce-starter-app/listeners/events/app-home-opened.js`. As we saw in the last post, the Starter Kit has an opinionated directory structure to resolve any ambiguities as to where modifications should be made. In this case, the events folder is responsible for defining all of our event responses, just like the shortcuts folder defined our slack command in the previous article. Search for the first occurrence of the following line:


```
client.views.publish
```


As the method name implies, this function uses a Slack SDK to call [an API named views.publish](https://api.slack.com/methods/views.publish). The main view for this event is created by a function called `authorization_success_screen`, which can be found in `apps/slack-salesforce-starter-app/user-interface/app-home/auth-success.js`. 

Let’s make a few changes to these files. On line 16, add this line to fetch the timestamp of the event:


```
let event_ts = event.event_ts;
```


Change both `authorization_success_screen` calls to include this variable as a new argument:


```
view: authorization_success_screen(
  currentuser.username,
  event_ts
)
```


Finally, open up `auth-success.js`, change the method signature to include event_ts, and modify the displayed string to include this information:


```
'use strict';

const { HomeTab, Blocks } = require('slack-block-builder');

const authorization_success_screen = (username, event_ts) => {
   
  // preceding code remains unchanged

       Blocks.Section({
           text: `It's ${event_ts}, and you are successfully authenticated to Salesforce as ${username}.`
       })
   );
// continued code remains unchanged
```


Commit this change, and deploy it to Heroku as before: 


```
$ git add .
$ git commit -m "Add event timestamp"
$ git push heroku main
```


When the deployment is done, navigate to your app’s tab in the left-hand Slack menu. You should see a different string, which shows the timestamp of when you opened the app.


### Creating a UI

Responding to `app_home_opened` can be a useful event to listen to whenever your app needs a centralized location to fetch data. Because of this, our next step will be to fetch data from Salesforce and present it in our Slack UI.

To design and present layouts, Slack provides a system known as [Block Kit](https://api.slack.com/block-kit). Just as HTML is a markup language for the web, and Visualforce is a markup language for Salesforce, Block Kit is a markup language for Slack—except it uses JSON. For example, here’s what a button designed in Block Kit might look like:


```
{
  "type": "button",
  "text": {
    "type": "plain_text",
    "text": "Save"
  },
  "style": "primary"
}
```


Block Kit ensures that every Slack App has a consistent user interface. Because of this, there’s a limited set of UI elements that you can use. 
 
When working with Block Kit, you design your layout in JSON. Then, you use the Slack API to POST that JSON to a channel, tab, or direct message.

We already have a system in place for listening to an event and presenting text, so let’s build on that foundation. Before we work in Slack, though, let’s add some data to our fresh Salesforce org. To launch your browser directly to your Salesforce org, you can run the following command:


```
sfdx force:org:open
```


In the Setup menu, search for the [Data Import Wizard](https://help.salesforce.com/s/articleView?id=sf.importing.htm&type=5). Choose CSV as your data type, then copy-paste the following lines into a new file called data.csv:


```
Contact First Name, Contact Last Name, Contact Description
Arden, Isabela, Lorem ipsum dolor sit amet
Rowina, Arti, Proin a est sit amet quam varius efficitur.
Aislin, Oedipus, Praesent et euismod sem
Sindri, Filbert, Proin facilisis sit amet libero vulputate sodales
Cyril, Gratien, Nulla at massa eu turpis venenatis egestas
```


Upload this file as your data source. Importing this data should only take a minute or two. You can navigate to the Contacts tab if you’d like to be extra sure and verify that these names exist.

Next, we’re going to make changes similar to the ones we made before when adding the event timestamp. A variable called `conn` is available to use, which serves as a connection to Salesforce. We can use it to query for Contact data, which is what we’re interested in displaying in Slack.

Navigate to `apps/slack-salesforce-starter-app/user-interface/app-home/auth-success.js`. We’ll **await** the resolving of the promise in this function, and we’ll include the existing `conn `variable as a new argument:


```
view: await authorization_success_screen(
                   currentuser.username,
                   event_ts,
                   conn
               )
```


And once again, open up `auth-success.js` and change the method signature to include `conn`. You also need to declare the function as **async**:


```
'use strict';

const { HomeTab, Blocks } = require('slack-block-builder');

const authorization_success_screen = async (username, event_ts, conn) => {
   
// continued code remains unchanged for now
```


Next, with this connection, we’re going to issue a query to Salesforce to get our newly created Contact records. We’ll then display them in the Home tab of our Slack app. 

Since we already have a connection to Salesforce, fetching the data is as easy as issuing an SQL query. Place this code right before the place where the `homeTab` variable is defined:


```
const result = await conn.query(
  `SELECT Name, Description FROM Contact`
);
let records = result.records;

let fields = records.map((record) => {
  return `*${record.Name}*: ${record.Description}`;
});
```


Then, at the bottom of the blocks method call, add these lines, which represent the UI you’re constructing out of Block Kit:

```
Blocks.Section({
  text: `It's ${event_ts}, and you are successfully authenticated to Salesforce as ${username}.`
}),
Blocks.Header({ text: 'Contacts' }),
Blocks.Divider(),
Blocks.Section({
  text: fields.join('\n')
})
```

If you navigate back to your Slack App’s Home tab, you’ll see your organization’s list of contacts!


![](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e0h9aadq69pq9hv7n6e4.png)

### Learning more

We’ve built a Slack app that fetches data from Salesforce and presents that data in a UI using a framework called Block Kit. In our next post, we’ll send data from Slack _back_ to Salesforce!

Before then, you might want to familiarize yourself with how Block Kit works. Slack provides the [Block Kit Builder](https://www.google.com/url?q=https://app.slack.com/block-kit-builder&sa=D&source=docs&ust=1642619847313479&usg=AOvVaw2XYSjzDa5SC3NPKL7hyOgo), which is a playground for their UI elements. Under the hood, the Slack Starter Kit uses the [Block Builder](https://www.blockbuilder.dev/) to simplify the UI assemblage we worked with.