|
1 | 1 | import {App, MessageShortcut, UsersSelectAction} from '@slack/bolt'; |
2 | 2 | import {WebClient} from '@slack/web-api'; |
3 | | -import {Actions, Header, Input, Message, Modal, Section, TextInput, UserSelect} from 'slack-block-builder'; |
| 3 | +import {Actions, BlockCollection, Header, Input, Message, Modal, Option, Section, StaticSelect, TextInput, UserSelect} from 'slack-block-builder'; |
| 4 | + |
| 5 | +// Utilities |
4 | 6 | import {getInfo} from './util/sheets'; |
5 | 7 | import {capitalize, parseCellPhone} from './util/parsing'; |
6 | 8 | import { signingSecret, token, port } from './config'; |
@@ -127,37 +129,78 @@ app.command('/help', async ({ack, respond}) => { |
127 | 129 | Section().fields( |
128 | 130 | '*/help*\nSends info about other commands.', |
129 | 131 | '*/info @[user]?*\nGets the contact info of a given user.' |
| 132 | + ), |
| 133 | + Section().fields( |
| 134 | + '*/submit-feedback*\nSubmits feedback about the slack bot.' |
130 | 135 | ) |
131 | 136 | ) |
132 | 137 | .buildToObject() |
133 | 138 | ); |
134 | 139 | }); |
135 | 140 |
|
136 | | -app.command('/modaltest', async ({ack, client, payload}) => { |
| 141 | +// /submit-feedback |
| 142 | +// Submits feedback about the slack bot. |
| 143 | +app.command('/submit-feedback', async ({ack, client, payload}) => { |
137 | 144 | await ack(); |
138 | | - const modal = Modal({title: 'This is a modal.', submit: 'Submit', callbackId: 'test-modal'}) |
| 145 | + |
| 146 | + const feedbackTypes = [ |
| 147 | + Option({text: 'Feature suggestion', value: 'feature_suggestion'}), |
| 148 | + Option({text: 'Feature feedback', value: 'feature_feedback'}), |
| 149 | + Option({text: 'Bug report', value: 'bug_report'}) |
| 150 | + ]; |
| 151 | + |
| 152 | + const modal = Modal({title: 'SEC Slack Bot Feedback', submit: 'Submit', callbackId: 'feedback-modal'}) |
139 | 153 | .blocks( |
140 | | - Section({text: 'Please input your personal information so that your data may be harvested.'}), |
141 | | - Input({label: 'Name', blockId: 'name-input'}) |
142 | | - .element(TextInput({actionId: 'name-action', placeholder: 'John Doe'})) |
| 154 | + Section({text: 'Please select what type of feedback to give, what feature your feedback concerns, and a brief description of your suggestion.'}), |
| 155 | + Input({label: 'Feedback type', blockId: 'type-select'}) |
| 156 | + .element(StaticSelect({actionId: 'type-action', placeholder: 'Select a feedback type'}) |
| 157 | + .options(feedbackTypes) |
| 158 | + .initialOption(feedbackTypes[0])) |
143 | 159 | .optional(false), |
144 | | - Input({label: 'Email address', blockId: 'email-input'}) |
145 | | - .element(TextInput({actionId: 'email-action', placeholder: '[email protected]'})) |
| 160 | + Input({label: 'Feature name', blockId: 'name-input'}) |
| 161 | + .element(TextInput({actionId: 'name-action', placeholder: 'The feature your feedback concerns.'})) |
146 | 162 | .optional(false), |
147 | | - Input({label: 'Phone number', blockId: 'phone-input'}) |
148 | | - .element(TextInput({actionId: 'phone-action', placeholder: '(650)-000-0000'})) |
149 | | - .optional(true) |
| 163 | + Input({label: 'Feedback description', blockId: 'desc-input'}) |
| 164 | + .element(TextInput({actionId: 'desc-action', placeholder: 'A brief description of your feedback.'}) |
| 165 | + .multiline(true)) |
| 166 | + .optional(false) |
150 | 167 | ) |
151 | 168 | .buildToObject(); |
152 | 169 | await client.views.open({trigger_id: payload.trigger_id, view: modal}); |
153 | 170 | }); |
154 | 171 |
|
155 | | -app.view('test-modal', async ({ack, view}) => { |
156 | | - await ack(); |
| 172 | +app.view('feedback-modal', async ({ack, client, body, view}) => { |
| 173 | + // Update feedback modal with close message |
| 174 | + await ack({ |
| 175 | + response_action: 'update', |
| 176 | + view: Modal({title: 'SEC Slack Bot Feedback'}) |
| 177 | + .blocks( |
| 178 | + Header({text: 'Your feedback was successfully submitted.'}), |
| 179 | + Section({text: 'This modal can be safely closed. Have a nice day!'}) |
| 180 | + ) |
| 181 | + .buildToObject() |
| 182 | + }); |
| 183 | + |
| 184 | + // Log feedback with relevant persons |
| 185 | + const type = view.state.values['type-select']['type-action'].selected_option?.value; |
157 | 186 | const name = view.state.values['name-input']['name-action'].value; |
158 | | - const email = view.state.values['email-input']['email-action'].value; |
159 | | - const phone = view.state.values['phone-input']['phone-action'].value; |
160 | | - console.log(`Received: name=${name} email=${email} phone=${phone}`) |
| 187 | + const desc = view.state.values['desc-input']['desc-action'].value; |
| 188 | + |
| 189 | + const users = ['U03GQC0A9MJ', 'U03GFNM1XA6']; // Kevin Yu, Ethan Liang |
| 190 | + const res = await client.conversations.open({users: users.join(',')}); |
| 191 | + if (!res.ok || !res.channel?.id) return; |
| 192 | + |
| 193 | + const blocks = BlockCollection( |
| 194 | + Header({text: `${body.user.name} submitted a new ${type}`}), |
| 195 | + Section({text: `*Name:* ${name}`}), |
| 196 | + Section({text: `*Desc:* ${desc}`}) |
| 197 | + ); |
| 198 | + |
| 199 | + await client.chat.postMessage({ |
| 200 | + channel: res.channel.id, |
| 201 | + blocks, |
| 202 | + text: `${body.user.name} submitted a new ${type}` |
| 203 | + }); |
161 | 204 | }); |
162 | 205 |
|
163 | 206 | ;(async () => { |
|
0 commit comments