From 57f97104c43963929172a426a86ef6b35d4ed268 Mon Sep 17 00:00:00 2001 From: Eden Zimbelman Date: Mon, 9 Nov 2026 14:55:04 -0800 Subject: [PATCH] feat(block-kit): add plan block example Co-Authored-By: Claude --- block-kit/README.md | 1 + block-kit/src/main/java/blocks/Plan.java | 55 ++++++++++++ block-kit/src/test/java/blocks/PlanTest.java | 88 ++++++++++++++++++++ 3 files changed, 144 insertions(+) create mode 100644 block-kit/src/main/java/blocks/Plan.java create mode 100644 block-kit/src/test/java/blocks/PlanTest.java diff --git a/block-kit/README.md b/block-kit/README.md index 4e54988..009c5c6 100644 --- a/block-kit/README.md +++ b/block-kit/README.md @@ -20,6 +20,7 @@ Read the [docs](https://docs.slack.dev/block-kit/) to learn concepts behind thes - **[Image](https://docs.slack.dev/reference/block-kit/blocks/image-block)**: Displays an image. [Implementation](./src/main/java/blocks/Image.java). - **[Input](https://docs.slack.dev/reference/block-kit/blocks/input-block)**: Collects information from users via elements. [Implementation](./src/main/java/blocks/Input.java). - **[Markdown](https://docs.slack.dev/reference/block-kit/blocks/markdown-block)**: Displays formatted markdown. [Implementation](./src/main/java/blocks/Markdown.java). +- **[Plan](https://docs.slack.dev/reference/block-kit/blocks/plan-block)**: Displays a collection of related tasks. [Implementation](./src/main/java/blocks/Plan.java). - **[Section](https://docs.slack.dev/reference/block-kit/blocks/section-block)**: Displays text, possibly alongside elements. [Implementation](./src/main/java/blocks/Section.java). - **[Task card](https://docs.slack.dev/reference/block-kit/blocks/task-card-block)**: Displays a single task, representing a single action. [Implementation](./src/main/java/blocks/TaskCard.java). - **[Video](https://docs.slack.dev/reference/block-kit/blocks/video-block)**: Displays an embedded video player. [Implementation](./src/main/java/blocks/Video.java). diff --git a/block-kit/src/main/java/blocks/Plan.java b/block-kit/src/main/java/blocks/Plan.java new file mode 100644 index 0000000..8879522 --- /dev/null +++ b/block-kit/src/main/java/blocks/Plan.java @@ -0,0 +1,55 @@ +package blocks; + +import com.slack.api.model.block.Blocks; +import com.slack.api.model.block.PlanBlock; +import com.slack.api.model.block.RichTextBlock; +import com.slack.api.model.block.element.RichTextSectionElement; +import java.util.List; + +/** + * Displays a collection of related tasks. + * {@link https://docs.slack.dev/reference/block-kit/blocks/plan-block/} + */ +public class Plan { + /** + * A plan block with multiple task cards in various states. + */ + public static PlanBlock example01() { + PlanBlock block = Blocks.plan(p -> p.title("Thinking completed") + .tasks(List.of( + Blocks.taskCard(t -> t.taskId("call_001") + .title("Fetched user profile information") + .status("in_progress") + .details(RichTextBlock.builder() + .blockId("viMWO") + .elements(List.of(RichTextSectionElement.builder() + .elements(List.of(RichTextSectionElement.Text.builder() + .text("Searched database...") + .build())) + .build())) + .build()) + .output(RichTextBlock.builder() + .blockId("viMWO") + .elements(List.of(RichTextSectionElement.builder() + .elements(List.of(RichTextSectionElement.Text.builder() + .text("Profile data loaded") + .build())) + .build())) + .build())), + Blocks.taskCard(t -> t.taskId("call_002") + .title("Checked user permissions") + .status("in_progress")), + Blocks.taskCard(t -> t.taskId("call_003") + .title("Generated comprehensive user report") + .status("complete") + .output(RichTextBlock.builder() + .blockId("crsk") + .elements(List.of(RichTextSectionElement.builder() + .elements(List.of(RichTextSectionElement.Text.builder() + .text("15 data points compiled") + .build())) + .build())) + .build()))))); + return block; + } +} diff --git a/block-kit/src/test/java/blocks/PlanTest.java b/block-kit/src/test/java/blocks/PlanTest.java new file mode 100644 index 0000000..ef88715 --- /dev/null +++ b/block-kit/src/test/java/blocks/PlanTest.java @@ -0,0 +1,88 @@ +package blocks; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import com.google.gson.JsonParser; +import com.slack.api.model.block.PlanBlock; +import com.slack.api.util.json.GsonFactory; +import org.junit.jupiter.api.Test; + +public class PlanTest { + @Test + public void testExample01() { + PlanBlock block = Plan.example01(); + String actual = GsonFactory.createSnakeCase().toJson(block); + String expected = """ + { + "type": "plan", + "title": "Thinking completed", + "tasks": [ + { + "type": "task_card", + "task_id": "call_001", + "title": "Fetched user profile information", + "status": "in_progress", + "details": { + "type": "rich_text", + "block_id": "viMWO", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Searched database..." + } + ] + } + ] + }, + "output": { + "type": "rich_text", + "block_id": "viMWO", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "Profile data loaded" + } + ] + } + ] + } + }, + { + "type": "task_card", + "task_id": "call_002", + "title": "Checked user permissions", + "status": "in_progress" + }, + { + "type": "task_card", + "task_id": "call_003", + "title": "Generated comprehensive user report", + "status": "complete", + "output": { + "type": "rich_text", + "block_id": "crsk", + "elements": [ + { + "type": "rich_text_section", + "elements": [ + { + "type": "text", + "text": "15 data points compiled" + } + ] + } + ] + } + } + ] + } + """; + assertEquals(JsonParser.parseString(expected), JsonParser.parseString(actual)); + } +}