Skip to content
This repository was archived by the owner on May 27, 2025. It is now read-only.

Commit 5bb05db

Browse files
updated to Block Kit and Block Kit modals instead of legacy attachments and dialogs
1 parent 36943ef commit 5bb05db

File tree

4 files changed

+118
-61
lines changed

4 files changed

+118
-61
lines changed

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"description": "Sample Slack app that responds to an Slack slash command with an interactive message",
66
"scripts": {
77
"test": "echo \"Error: no test specified\" && exit 1",
8-
"start": "DEBUG=slash-command-template node src/index.js"
8+
"start": "DEBUG=slash-command-template node src/index.js",
9+
"dev": "nodemon src/index.js"
910
},
1011
"authors": [
1112
"Sachin Ranchod <sranchod@slack-corp.com>",
@@ -22,5 +23,8 @@
2223
"dotenv": "^4.0.0",
2324
"express": "^4.15.2",
2425
"tsscmp": "^1.0.6"
26+
},
27+
"devDependencies": {
28+
"nodemon": "^1.19.4"
2529
}
2630
}

src/index.js

Lines changed: 82 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -44,48 +44,100 @@ app.post('/command', (req, res) => {
4444
if (signature.isVerified(req)) {
4545
// create the dialog payload - includes the dialog structure, Slack API token,
4646
// and trigger ID
47-
const dialog = {
47+
const view = {
4848
token: process.env.SLACK_ACCESS_TOKEN,
4949
trigger_id,
50-
dialog: JSON.stringify({
51-
title: 'Submit a helpdesk ticket',
50+
view: JSON.stringify({
51+
type: 'modal',
52+
title: {
53+
type: 'plain_text',
54+
text: 'Submit a helpdesk ticket'
55+
},
5256
callback_id: 'submit-ticket',
53-
submit_label: 'Submit',
54-
elements: [
57+
submit: {
58+
type: 'plain_text',
59+
text: 'Submit'
60+
},
61+
blocks: [
5562
{
56-
label: 'Title',
57-
type: 'text',
58-
name: 'title',
59-
value: text,
60-
hint: '30 second summary of the problem',
63+
block_id: 'title_block',
64+
type: 'input',
65+
label: {
66+
type: 'plain_text',
67+
text: 'Title'
68+
},
69+
element: {
70+
action_id: 'title',
71+
type: 'plain_text_input'
72+
},
73+
hint: {
74+
type: 'plain_text',
75+
text: '30 second summary of the problem'
76+
}
6177
},
6278
{
63-
label: 'Description',
64-
type: 'textarea',
65-
name: 'description',
66-
optional: true,
79+
block_id: 'description_block',
80+
type: 'input',
81+
label: {
82+
type: 'plain_text',
83+
text: 'Description'
84+
},
85+
element: {
86+
action_id: 'description',
87+
type: 'plain_text_input',
88+
multiline: true
89+
},
90+
optional: true
6791
},
6892
{
69-
label: 'Urgency',
70-
type: 'select',
71-
name: 'urgency',
72-
options: [
73-
{ label: 'Low', value: 'Low' },
74-
{ label: 'Medium', value: 'Medium' },
75-
{ label: 'High', value: 'High' },
76-
],
77-
},
78-
],
79-
}),
93+
block_id: 'urgency_block',
94+
type: 'input',
95+
label: {
96+
type: 'plain_text',
97+
text: 'Importance'
98+
},
99+
element: {
100+
action_id: 'urgency',
101+
type: 'static_select',
102+
options: [
103+
{
104+
text: {
105+
type: "plain_text",
106+
text: "High"
107+
},
108+
value: "high"
109+
},
110+
{
111+
text: {
112+
type: "plain_text",
113+
text: "Medium"
114+
},
115+
value: "medium"
116+
},
117+
{
118+
text: {
119+
type: "plain_text",
120+
text: "Low"
121+
},
122+
value: "low"
123+
}
124+
]
125+
},
126+
optional: true
127+
}
128+
]
129+
})
80130
};
81131

132+
console.log('open view')
133+
82134
// open the dialog by calling dialogs.open method and sending the payload
83-
axios.post(`${apiUrl}/dialog.open`, qs.stringify(dialog))
135+
axios.post(`${apiUrl}/views.open`, qs.stringify(view))
84136
.then((result) => {
85-
debug('dialog.open: %o', result.data);
137+
debug('views.open: %o', result.data);
86138
res.send('');
87139
}).catch((err) => {
88-
debug('dialog.open call failed: %o', err);
140+
debug('views.open call failed: %o', err);
89141
res.sendStatus(500);
90142
});
91143
} else {
@@ -103,14 +155,14 @@ app.post('/interactive', (req, res) => {
103155

104156
// check that the verification token matches expected value
105157
if (signature.isVerified(req)) {
106-
debug(`Form submission received: ${body.submission.trigger_id}`);
158+
debug(`Form submission received: ${body.view}`);
107159

108160
// immediately respond with a empty 200 response to let
109161
// Slack know the command was received
110162
res.send('');
111163

112164
// create Helpdesk ticket
113-
ticket.create(body.user.id, body.submission);
165+
ticket.create(body.user.id, body.view);
114166
} else {
115167
debug('Token mismatch');
116168
res.sendStatus(404);

src/ticket.js

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -13,33 +13,33 @@ const sendConfirmation = (ticket) => {
1313
channel: ticket.userId,
1414
as_user: true,
1515
text: 'Helpdesk ticket created!',
16-
attachments: JSON.stringify([
16+
blocks: JSON.stringify([
1717
{
18-
title: `Ticket created for ${ticket.userEmail}`,
19-
// Get this from the 3rd party helpdesk system
20-
title_link: 'http://example.com',
21-
text: ticket.text,
22-
fields: [
23-
{
24-
title: 'Title',
25-
value: ticket.title,
26-
},
27-
{
28-
title: 'Description',
29-
value: ticket.description || 'None provided',
30-
},
31-
{
32-
title: 'Status',
33-
value: 'Open',
34-
short: true,
35-
},
36-
{
37-
title: 'Urgency',
38-
value: ticket.urgency,
39-
short: true,
40-
},
41-
],
18+
type: 'section',
19+
text: {
20+
type: 'mrkdwn',
21+
text: '*Helpdesk ticket created!*'
22+
}
23+
},
24+
{
25+
type: 'divider'
26+
},
27+
{
28+
type: 'section',
29+
text: {
30+
type: 'mrkdwn',
31+
text: `*Title*\n${ticket.title}\n\n*Description*\n${ticket.description}`
32+
}
4233
},
34+
{
35+
type: 'context',
36+
elements: [
37+
{
38+
type: 'mrkdwn',
39+
text: `*Urgency*: ${ticket.urgency}`
40+
}
41+
]
42+
}
4343
]),
4444
})).then((result) => {
4545
debug('sendConfirmation: %o', result.data);
@@ -51,7 +51,8 @@ const sendConfirmation = (ticket) => {
5151

5252
// Create helpdesk ticket. Call users.find to get the user's email address
5353
// from their user ID
54-
const create = (userId, submission) => {
54+
const create = (userId, view) => {
55+
let values = view.state.values
5556
const ticket = {};
5657

5758
const fetchUserEmail = new Promise((resolve, reject) => {
@@ -64,9 +65,9 @@ const create = (userId, submission) => {
6465
fetchUserEmail.then((result) => {
6566
ticket.userId = userId;
6667
ticket.userEmail = result;
67-
ticket.title = submission.title;
68-
ticket.description = submission.description;
69-
ticket.urgency = submission.urgency;
68+
ticket.title = values.title_block.title.value;
69+
ticket.description = values.description_block.description.value;
70+
ticket.urgency = values.urgency_block.urgency.selected_option.text.text;
7071
sendConfirmation(ticket);
7172

7273
return ticket;

src/verifySignature.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const crypto = require('crypto');
22
const timingSafeCompare = require('tsscmp');
33

4-
const isVerified = (req) => {
4+
const isVerified = (req) => {
55
const signature = req.headers['x-slack-signature'];
66
const timestamp = req.headers['x-slack-request-timestamp'];
77
const hmac = crypto.createHmac('sha256', process.env.SLACK_SIGNING_SECRET);

0 commit comments

Comments
 (0)