Skip to content

Commit 7d0c132

Browse files
author
Evan Rittenhouse
committed
Make code review changes
1 parent 04e8834 commit 7d0c132

File tree

4 files changed

+151
-71
lines changed

4 files changed

+151
-71
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ All released versions are available on the Maven Central repositories. The lates
6161
|groupId:artifactId|Description|
6262
|---|---|
6363
|[**com.slack.api:slack-api-model**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model)|This module is a collection of the classes representing the [Slack core objects](https://api.slack.com/types) such as conversations, messages, users, surfaces, and blocks. As this one is an essential part of the SDK, all others depend on this.|
64-
|[**com.slack.api:slack-api-model-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model-kotlin-extension)|This contains the Block Kit Kotlin DSL builder, which allows you to define block kit structures via a Kotlin-native DSL.|
64+
|[**com.slack.api:slack-api-model-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-model-kotlin-extension)|This contains the Block Kit Kotlin DSL builder, which allows you to define Block Kit structures via a Kotlin-native DSL.|
6565
|[**com.slack.api:slack-api-client**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-client)|This is a collection of the Slack API clients. The supported are Basic API Methods, RTM (Real Time Messaging) API, SCIM API, Audit Logs API, and Status API.|
6666
|[**com.slack.api:slack-api-client-kotlin-extension**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-api-client-kotlin-extension)|This contains extension methods for various slack client message builders so you can seamlessly use the Block Kit Kotlin DSL directly on the Java message builders.|
6767
|[**com.slack.api:slack-app-backend**](https://search.maven.org/search?q=g:com.slack.api%20AND%20a:slack-app-backend)|This module is a set of Slack app server-side handlers and data classes for Events API, Interactive Components, Slash Commands, Actions, and OAuth flow. These are used by Bolt framework as the foundation of it in primitive layers.|

docs/guides/app-home.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,26 @@ app.event(AppHomeOpenedEvent::class.java) { event, ctx ->
101101
}
102102
```
103103

104+
You can also build the view in the above example with the [Block Kit Kotlin DSL]({{ site.url | append: site.baseurl }}/guides/composing-messages#block-kit-kotlin-dsl) like so:
105+
106+
```kotlin
107+
// These imports are necessary for this code
108+
import com.slack.api.model.kotlin_extension.view.blocks
109+
import com.slack.api.model.view.Views.view
110+
111+
val appHomeView = view {
112+
it.type("home")
113+
.blocks {
114+
section {
115+
markdownText(":wave: Hello, App Home! (Last updated: ${now}")
116+
}
117+
image {
118+
imageUrl("https://www.example.com/foo.png")
119+
}
120+
}
121+
}
122+
```
123+
104124
### Under the Hood
105125

106126
Refer to [the Events API guide]({{ site.url | append: site.baseurl }}/guides/events-api).

docs/guides/composing-messages.md

Lines changed: 79 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -74,43 +74,46 @@ You can use this way also for building a message for Incoming Webhooks and `resp
7474
---
7575
## Block Kit Kotlin DSL
7676

77-
If you're using Kotlin, the Java Slack SDK also provides Kotlin-style builders which you can use to build your block kit structures.
77+
If you're using Kotlin, the Java Slack SDK also provides Kotlin-style builders which you can use to build your Block Kit structures.
7878

7979
```kotlin
80+
import com.slack.api.Slack
8081
import com.slack.api.model.block.Blocks.*
8182
import com.slack.api.model.kotlin_extension.request.chat.blocks
8283

84+
val slack = Slack.getInstance()
85+
val token = System.getenv("token")
8386
val response = slack.methods(token).chatPostMessage { req -> req
84-
.channel("C1234567")
85-
.blocks {
86-
section {
87-
// "text" fields can be constructed via plainText() and markdownText()
88-
markdownText("*Please select a restaurant:*")
89-
}
90-
divider()
91-
actions {
92-
// To align with the JSON structure, you could put the elements { } block around the buttons but for brevity it can be omitted
93-
// The same is true for things such as the section block's "accessory" container
94-
button {
95-
// For instances where only plain text is acceptable, the field's name can be filled with plain text inputs
96-
text("Farmhouse", emoji = true)
97-
value("v1")
98-
}
99-
button {
100-
text("Kin Khao", emoji = true)
101-
value("v2")
102-
}
103-
}
87+
.channel("C1234567")
88+
.blocks {
89+
section {
90+
// "text" fields can be constructed via plainText() and markdownText()
91+
markdownText("*Please select a restaurant:*")
92+
}
93+
divider()
94+
actions {
95+
// To align with the JSON structure, you could put the elements { } block around the buttons but for brevity it can be omitted
96+
// The same is true for things such as the section block's "accessory" container
97+
button {
98+
// For instances where only plain text is acceptable, the field's name can be filled with plain text inputs
99+
text("Farmhouse", emoji = true)
100+
value("v1")
101+
}
102+
button {
103+
text("Kin Khao", emoji = true)
104+
value("v2")
105+
}
104106
}
107+
}
105108
}
106109
```
107110

108111
### Installation
109112

110113
You can add the Block Kit Kotlin DSL via 2 artifacts:
111114

112-
* The slack model kotlin extension, which adds the Kotlin DSL itself as well as the standalone `withBlocks { }` builder
113-
* The slack client kotlin extension, which adds the `.blocks { }` extension function to various Slack Client builders for seamless use of the DSL with the Java builders
115+
* The `slack-api-model` Kotlin extension, which adds the Kotlin DSL itself as well as the standalone `withBlocks { }` builder and `View.ViewBuilder`'s `.blocks { }` extension function
116+
* The `slack-api-client` Kotlin extension, which adds the `.blocks { }` extension function to `MethodsClient`'s request object builders for seamless use of the DSL with the Java builders
114117
* The `.blocks { }` extension function is available on the following Java builders:
115118
* ChatPostEphemeralRequestBuilder
116119
* ChatPostMessageRequestBuilder
@@ -121,95 +124,101 @@ You can add the Block Kit Kotlin DSL via 2 artifacts:
121124

122125
```groovy
123126
dependencies {
124-
implementation "com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}"
125-
implementation "com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}"
127+
implementation "com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}"
128+
implementation "com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}"
126129
}
127130
```
128131

129132
**Adding via Gradle Kotlin DSL:**
130133

131134
```kotlin
132135
dependencies {
133-
implementation("com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}")
134-
implementation("com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}")
136+
implementation("com.slack.api:slack-api-model-kotlin-extension:{{ site.sdkLatestVersion }}")
137+
implementation("com.slack.api:slack-api-client-kotlin-extension:{{ site.sdkLatestVersion }}")
135138
}
136139
```
137140

138141
### Notable examples and features
139142

140143
**Standalone withBlocks builder which comes with the model extension**:
141144

145+
You can create lists of blocks outside of the `slack-api-client` Kotlin extension functions with the `withBlocks { }` builder.
146+
142147
```kotlin
143148
import com.slack.api.model.kotlin_extension.block.withBlocks
144149

145-
val constructedMessage = withBlocks {
146-
section {
147-
plainText("Now this can be passed to anything that requires a list of LayoutBlocks")
148-
}
150+
val blocks = withBlocks {
151+
section {
152+
plainText("Now this can be passed to anything that requires a list of LayoutBlocks")
153+
}
149154
}
150155
```
151156

152157
**Type safe enums for inputs which require specific string inputs**:
153158

159+
Type-safe enums are available for properties of some block elements which require specific input strings. With this, you get the benefit of verifying your inputs are correct at compile time and you gain access to Kotlin enum features such as being able to iterate over or retrieve all possible values for these inputs. Versions of these inputs which accept strings are also available, if you prefer.
160+
154161
```kotlin
155162
import com.slack.api.model.kotlin_extension.block.element.ButtonStyle
156163
import com.slack.api.model.kotlin_extension.block.element.ConversationType
157164
import com.slack.api.model.kotlin_extension.block.withBlocks
158165

159-
val message = withBlocks {
160-
section {
161-
plainText("Please select the person or group you would like to send a cat GIF to.")
162-
163-
// "accessory" is provided here, but it can be omitted for brevity
164-
accessory {
165-
conversationsSelect {
166-
// Or alternatively, provide strings via filter("im", "mpim") if you'd prefer
167-
filter(ConversationType.IM, ConversationType.MULTIPARTY_IM)
168-
placeholder("Where should we send the cat?")
169-
170-
confirm {
171-
title("Confirm destination")
172-
plainText("Are you sure you want to send a cat GIF to this person or group?")
173-
confirm("Yes, send it")
174-
deny("Don't send it")
175-
176-
style(ButtonStyle.PRIMARY)
177-
}
178-
}
166+
val blocks = withBlocks {
167+
section {
168+
plainText("Please select the person or group you would like to send a cat GIF to.")
169+
170+
// "accessory" is provided here, but it can be omitted for brevity
171+
accessory {
172+
conversationsSelect {
173+
// Or alternatively, provide strings via filter("im", "mpim") if you'd prefer
174+
filter(ConversationType.IM, ConversationType.MULTIPARTY_IM)
175+
placeholder("Where should we send the cat?")
176+
177+
confirm {
178+
title("Confirm destination")
179+
plainText("Are you sure you want to send a cat GIF to this person or group?")
180+
confirm("Yes, send it")
181+
deny("Don't send it")
182+
183+
style(ButtonStyle.PRIMARY)
179184
}
185+
}
180186
}
187+
}
181188
}
182189
```
183190

184191
**Write DSL extension functions for message templating**:
185192

193+
Because it is a Kotlin DSL, you benefit from Kotlin language features while you are constructing your messages, one of which being able to create extension functions which reproduce common Block Kit structures. This makes your code less repetitive and easier to read. You also benefit from being able to use conditionals and loops as you construct your blocks.
194+
186195
```kotlin
187196
import com.slack.api.model.kotlin_extension.block.ActionsBlockBuilder
188197
import com.slack.api.model.kotlin_extension.block.withBlocks
189198

190199
fun ActionsBlockBuilder.presentOptions(vararg optionNames: String, prompt: String? = null) {
191-
staticSelect {
192-
if (prompt != null) {
193-
placeholder(prompt)
194-
}
195-
196-
options {
197-
for (optionName in optionNames) {
198-
option {
199-
plainText(optionName)
200-
value(optionName.toLowerCase())
201-
}
202-
}
200+
staticSelect {
201+
if (prompt != null) {
202+
placeholder(prompt)
203+
}
204+
205+
options {
206+
for (optionName in optionNames) {
207+
option {
208+
plainText(optionName)
209+
value(optionName.toLowerCase())
203210
}
211+
}
204212
}
213+
}
205214
}
206215

207-
val message = withBlocks {
208-
section {
209-
markdownText("Please select your favorite color.")
210-
}
211-
actions {
212-
presentOptions("Green", "Red", "Blue", "Yellow", "Orange", "Black", prompt = "Pick a color...")
213-
}
216+
val blocks = withBlocks {
217+
section {
218+
markdownText("Please select your favorite color.")
219+
}
220+
actions {
221+
presentOptions("Green", "Red", "Blue", "Yellow", "Orange", "Black", prompt = "Pick a color...")
222+
}
214223
}
215224
```

docs/guides/modals.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,57 @@ val res = ctx.client().viewsOpen { it
228228
}
229229
```
230230
231+
Alternatively, you can use the [Block Kit DSL]({{ site.url | append: site.baseurl }}/guides/composing-messages#block-kit-kotlin-dsl) in conjunction with the Java Builder to construct your view. The Java example above would look like this in Kotlin:
232+
233+
```kotlin
234+
import com.slack.api.model.kotlin_extension.view.blocks
235+
import com.slack.api.model.view.Views.*
236+
237+
fun buildView(): View {
238+
return view { thisView -> thisView
239+
.callbackId("meeting-arrangement")
240+
.type("modal")
241+
.notifyOnClose(true)
242+
.title(viewTitle { it.type("plain_text").text("Meeting Arrangement").emoji(true) })
243+
.submit(viewSubmit { it.type("plain_text").text("Submit").emoji(true) })
244+
.close(viewClose { it.type("plain_text").text("Cancel").emoji(true) })
245+
.privateMetadata("""{"response_url":"https://hooks.slack.com/actions/T1ABCD2E12/330361579271/0dAEyLY19ofpLwxqozy3firz"}""")
246+
.blocks {
247+
section {
248+
blockId("category-block")
249+
markdownText("Select a category of the meeting!")
250+
staticSelect {
251+
actionId("category-selection-action")
252+
placeholder("Select a category")
253+
options {
254+
option {
255+
description("Customer")
256+
value("customer")
257+
}
258+
option {
259+
description("Partner")
260+
value("partner")
261+
}
262+
option {
263+
description("Internal")
264+
value("internal")
265+
}
266+
}
267+
}
268+
}
269+
input {
270+
blockId("agenda-block")
271+
plainTextInput {
272+
actionId("agenda-action")
273+
multiline(true)
274+
}
275+
label("Detailed Agenda", emoji = true)
276+
}
277+
}
278+
}
279+
}
280+
```
281+
231282
### `"block_actions"` requests
232283
233284
Basically it's the same with [Interactive Components]({{ site.url | append: site.baseurl }}/guides/interactive-components) but the only difference is that a payload coming from a modal has `view` and also its `private_metadata`

0 commit comments

Comments
 (0)