Skip to content

Commit 0be98fb

Browse files
committed
Fix wrong code snippets for block_actions in modals
1 parent 7f74b09 commit 0be98fb

File tree

3 files changed

+87
-15
lines changed

3 files changed

+87
-15
lines changed

bolt/src/test/java/test_locally/docs/ModalsTest.java

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package test_locally.docs;
22

3+
import com.google.gson.Gson;
34
import com.slack.api.bolt.App;
45
import com.slack.api.bolt.AppConfig;
56
import com.slack.api.methods.response.views.ViewsUpdateResponse;
67
import com.slack.api.model.view.View;
78
import com.slack.api.model.view.ViewState;
9+
import com.slack.api.util.json.GsonFactory;
810
import org.junit.Test;
911

1012
import java.util.HashMap;
@@ -21,7 +23,7 @@
2123
// https://slack.dev/java-slack-sdk/guides/modals
2224
public class ModalsTest {
2325

24-
App app = new App(AppConfig.builder().signingSecret("foo").signingSecret("xoxb-xxx").build());
26+
App app = new App(AppConfig.builder().signingSecret("foo").singleTeamBotToken("xoxb-xxx").build());
2527

2628
View buildView() {
2729
return view(view -> view
@@ -62,17 +64,45 @@ public void example() {
6264
assertEquals(2, view.getBlocks().size());
6365
}
6466

65-
View buildViewByCategory(String categoryId, String privateMetadata) {
66-
return null; // TODO
67+
private static final Gson gson = GsonFactory.createSnakeCase();
68+
69+
static View buildViewByCategory(String categoryId, String privateMetadata) {
70+
Map<String, String> metadata = gson.fromJson(privateMetadata, Map.class);
71+
metadata.put("categoryId", categoryId);
72+
String updatedPrivateMetadata = gson.toJson(metadata);
73+
return view(view -> view
74+
.callbackId("meeting-arrangement")
75+
.type("modal")
76+
.notifyOnClose(true)
77+
.title(viewTitle(title -> title.type("plain_text").text("Meeting Arrangement").emoji(true)))
78+
.submit(viewSubmit(submit -> submit.type("plain_text").text("Submit").emoji(true)))
79+
.close(viewClose(close -> close.type("plain_text").text("Cancel").emoji(true)))
80+
.privateMetadata(updatedPrivateMetadata)
81+
.blocks(asBlocks(
82+
section(section -> section
83+
.blockId("category-block")
84+
.text(markdownText("You've selected \"" + categoryId + "\""))
85+
),
86+
input(input -> input
87+
.blockId("agenda-block")
88+
.element(plainTextInput(pti -> pti.actionId("agenda-action").multiline(true)))
89+
.label(plainText(pt -> pt.text("Detailed Agenda").emoji(true)))
90+
)
91+
))
92+
);
6793
}
6894

6995
@Test
7096
public void boltApp() {
97+
app.command("/doc-test", (req, ctx) -> {
98+
ctx.client().viewsOpen(r -> r.triggerId(ctx.getTriggerId()).view(buildView()));
99+
return ctx.ack();
100+
});
101+
71102
app.blockAction("category-selection-action", (req, ctx) -> {
103+
String categoryId = req.getPayload().getActions().get(0).getSelectedOption().getValue();
72104
View currentView = req.getPayload().getView();
73105
String privateMetadata = currentView.getPrivateMetadata();
74-
Map<String, Map<String, ViewState.Value>> stateValues = currentView.getState().getValues();
75-
String categoryId = stateValues.get("category-block").get("category-selection-action").getSelectedOption().getValue();
76106
View viewForTheCategory = buildViewByCategory(categoryId, privateMetadata);
77107
ViewsUpdateResponse viewsUpdateResp = ctx.client().viewsUpdate(r -> r
78108
.viewId(currentView.getId())

docs/guides/ja/modals.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -230,20 +230,42 @@ val res = ctx.client().viewsOpen { it
230230
基本的には「[インタラクティブコンポーネント]({{ site.url | append: site.baseurl }}/guides/ja/interactive-components)」で紹介したものと同じですが、違いとしてはそのペイロードに `view` としてモーダルの内容とその `private_metadata` が含まれていることが挙げられます。
231231

232232
```java
233+
import com.google.gson.Gson;
233234
import com.slack.api.model.view.View;
234235
import com.slack.api.model.view.ViewState;
235236
import com.slack.api.methods.response.views.ViewsUpdateResponse;
237+
import com.slack.api.util.json.GsonFactory;
236238
import java.util.Map;
237239

238240
View buildViewByCategory(String categoryId, String privateMetadata) {
239-
return null; // TODO
241+
Gson gson = GsonFactory.createSnakeCase();
242+
Map<String, String> metadata = gson.fromJson(privateMetadata, Map.class);
243+
metadata.put("categoryId", categoryId);
244+
String updatedPrivateMetadata = gson.toJson(metadata);
245+
246+
return view(view -> view
247+
.callbackId("meeting-arrangement")
248+
.type("modal")
249+
.notifyOnClose(true)
250+
.title(viewTitle(title -> title.type("plain_text").text("Meeting Arrangement").emoji(true)))
251+
.submit(viewSubmit(submit -> submit.type("plain_text").text("Submit").emoji(true)))
252+
.close(viewClose(close -> close.type("plain_text").text("Cancel").emoji(true)))
253+
.privateMetadata(updatedPrivateMetadata)
254+
.blocks(asBlocks(
255+
section(section -> section.blockId("category-block").text(markdownText("You've selected \"" + categoryId + "\""))),
256+
input(input -> input
257+
.blockId("agenda-block")
258+
.element(plainTextInput(pti -> pti.actionId("agenda-action").multiline(true)))
259+
.label(plainText(pt -> pt.text("Detailed Agenda").emoji(true)))
260+
)
261+
))
262+
);
240263
}
241264

242265
app.blockAction("category-selection-action", (req, ctx) -> {
266+
String categoryId = req.getPayload().getActions().get(0).getSelectedOption().getValue();
243267
View currentView = req.getPayload().getView();
244268
String privateMetadata = currentView.getPrivateMetadata();
245-
Map<String, Map<String, ViewState.Value>> stateValues = currentView.getState().getValues();
246-
String categoryId = stateValues.get("category-block").get("category-selection-action").getSelectedOption().getValue();
247269
View viewForTheCategory = buildViewByCategory(categoryId, privateMetadata);
248270
ViewsUpdateResponse viewsUpdateResp = ctx.client().viewsUpdate(r -> r
249271
.viewId(currentView.getId())
@@ -258,10 +280,9 @@ Kotlin で書くとこのようになります。
258280

259281
```kotlin
260282
app.blockAction("category-selection-action") { req, ctx ->
283+
val categoryId = req.payload.actions[0].selectedOption.value
261284
val currentView = req.payload.view
262285
val privateMetadata = currentView.privateMetadata
263-
val stateValues = currentView.state.values
264-
val categoryId = stateValues["category-block"]!!["category-selection-action"]!!.selectedOption.value
265286
val viewForTheCategory = buildViewByCategory(categoryId, privateMetadata)
266287
val viewsUpdateResp = ctx.client().viewsUpdate { it
267288
.viewId(currentView.id)

docs/guides/modals.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -232,20 +232,42 @@ val res = ctx.client().viewsOpen { it
232232
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`
233233

234234
```java
235+
import com.google.gson.Gson;
235236
import com.slack.api.model.view.View;
236237
import com.slack.api.model.view.ViewState;
237238
import com.slack.api.methods.response.views.ViewsUpdateResponse;
239+
import com.slack.api.util.json.GsonFactory;
238240
import java.util.Map;
239241

240242
View buildViewByCategory(String categoryId, String privateMetadata) {
241-
return null; // TODO
243+
Gson gson = GsonFactory.createSnakeCase();
244+
Map<String, String> metadata = gson.fromJson(privateMetadata, Map.class);
245+
metadata.put("categoryId", categoryId);
246+
String updatedPrivateMetadata = gson.toJson(metadata);
247+
248+
return view(view -> view
249+
.callbackId("meeting-arrangement")
250+
.type("modal")
251+
.notifyOnClose(true)
252+
.title(viewTitle(title -> title.type("plain_text").text("Meeting Arrangement").emoji(true)))
253+
.submit(viewSubmit(submit -> submit.type("plain_text").text("Submit").emoji(true)))
254+
.close(viewClose(close -> close.type("plain_text").text("Cancel").emoji(true)))
255+
.privateMetadata(updatedPrivateMetadata)
256+
.blocks(asBlocks(
257+
section(section -> section.blockId("category-block").text(markdownText("You've selected \"" + categoryId + "\""))),
258+
input(input -> input
259+
.blockId("agenda-block")
260+
.element(plainTextInput(pti -> pti.actionId("agenda-action").multiline(true)))
261+
.label(plainText(pt -> pt.text("Detailed Agenda").emoji(true)))
262+
)
263+
))
264+
);
242265
}
243266

244267
app.blockAction("category-selection-action", (req, ctx) -> {
268+
String categoryId = req.getPayload().getActions().get(0).getSelectedOption().getValue();
245269
View currentView = req.getPayload().getView();
246270
String privateMetadata = currentView.getPrivateMetadata();
247-
Map<String, Map<String, ViewState.Value>> stateValues = currentView.getState().getValues();
248-
String categoryId = stateValues.get("category-block").get("category-selection-action").getSelectedOption().getValue();
249271
View viewForTheCategory = buildViewByCategory(categoryId, privateMetadata);
250272
ViewsUpdateResponse viewsUpdateResp = ctx.client().viewsUpdate(r -> r
251273
.viewId(currentView.getId())
@@ -260,10 +282,9 @@ It looks like below in Kotlin.
260282

261283
```kotlin
262284
app.blockAction("category-selection-action") { req, ctx ->
285+
val categoryId = req.payload.actions[0].selectedOption.value
263286
val currentView = req.payload.view
264287
val privateMetadata = currentView.privateMetadata
265-
val stateValues = currentView.state.values
266-
val categoryId = stateValues["category-block"]!!["category-selection-action"]!!.selectedOption.value
267288
val viewForTheCategory = buildViewByCategory(categoryId, privateMetadata)
268289
val viewsUpdateResp = ctx.client().viewsUpdate { it
269290
.viewId(currentView.id)

0 commit comments

Comments
 (0)