feat(block-kit): add data_table layout block - #1613
Conversation
Add the new `data_table` Block Kit layout block to the model: DataTableBlock plus its cell model (DataTableCell interface with RawTextDataTableCell, RawNumberDataTableCell, and RichTextBlock for rich_text cells), the GsonDataTableCellFactory deserializer, factory registration, and a `dataTable` builder DSL entry. Ref: https://docs.slack.dev/reference/block-kit/blocks/data-table-block Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #1613 +/- ##
============================================
- Coverage 72.80% 72.75% -0.05%
- Complexity 4551 4556 +5
============================================
Files 483 484 +1
Lines 14456 14479 +23
Branches 1513 1513
============================================
+ Hits 10524 10534 +10
- Misses 3037 3047 +10
- Partials 895 898 +3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. |
…table # Conflicts: # slack-api-model/src/main/java/com/slack/api/util/json/GsonLayoutBlockFactory.java # slack-api-model/src/test/java/test_locally/api/model/block/BlockKitTest.java
Mirror the reviewed node SDK PR (slackapi/node-slack-sdk#2638): - Correct the max row count: the model previously stated up to 100 data rows (101 including header); the reference documents 201 rows (200 data rows plus header). The 100 cap was page_size, not the row maximum. Drop the stale count from the javadoc rather than restate it. - Align each field's javadoc with the data-table-block reference Fields table verbatim (rows, caption, page_size, row_header_column_index). - Trim RawTextDataTableCell / RawNumberDataTableCell to the terse, docs-minimal descriptions (drop the invented sorting/formatting tails); document value and text per the docs. Ref: https://docs.slack.dev/reference/block-kit/blocks/data-table-block Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Blocks.java keeps the recently-added blocks (Alert, Card, Carousel, Container, TaskCard) in a cluster at the end rather than slotting them alphabetically into the original core entries. Move the dataTable(...) builder into that cluster (after container, before taskCard) so a net-new block sits with its peers instead of splitting the old core from the new group. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…ta_table The data_table cells (raw_text / raw_number / rich_text) are the same cell model the table block uses. Rather than ship a parallel DataTableCell family, adopt the shared TableCell interface and its RawTextTableCell / RawNumberTableCell implementations in com.slack.api.model.block.composition, deserialized by a single GsonTableCellFactory: - Remove DataTableCell, RawTextDataTableCell, RawNumberDataTableCell, and GsonDataTableCellFactory. - Add TableCell, RawTextTableCell, RawNumberTableCell (in ...block.composition) and GsonTableCellFactory (in ...util.json). - DataTableBlock.rows is now List<List<TableCell>>; RichTextBlock implements TableCell; the client and model-test GsonFactory register TableCell -> GsonTableCellFactory. This is the same cell model the sibling table-block PR (#1611) introduces, placed in the same package with identical definitions, so whichever of the two lands second drops the now-duplicate files in a trivial merge. Mirrors how node (@slack/types composition objects) and python (slack_sdk basic_components) also share one cell model across both blocks. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…bject Rename the concrete TableCell implementations from RawTextTableCell / RawNumberTableCell to RawTextObject / RawNumberObject, matching the composition-object naming used by the other SDKs (python RawTextObject / RawNumberObject) and this repo's own ...Object grammar (PlainTextObject, MarkdownTextObject, OptionObject). The shared TableCell interface is the supertype the list is parameterized on (Java has no union types, so List<List<TableCell>> is how the raw_text | raw_number | rich_text union is expressed); only the implementation names change. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…import - GsonLayoutBlockFactory: move the DataTableBlock case into alphabetical order (between ContextBlock and DividerBlock) instead of after SectionBlock. - RichTextBlock: import com.slack.api.model.block.composition.TableCell and use the simple name in the implements clause rather than the fully qualified type inline. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
The raw_number schema marks text as required (required: [type, value, text], text minLength 1) — the javadoc wrongly called it optional. Match the schema: text carries the display representation of the value and must be at least one character long. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Keep the text-is-display + min-length note, drop the "(for example a formatted string)" aside. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Restructure RawNumberObject and RawTextObject to per-field javadoc, mirroring the node @slack/types descriptions and matching this repo's own per-field convention (OptionObject, ConfirmationDialogObject): - class: "Defines an object containing a numeric value." / "...some text." - value: "The numeric value." - text (number): "The text used to display the value. The minimum length is 1 character." - text (text): "The text for the block. The minimum length is 1 character." Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
Add BlockCompositions.rawText(...) and rawNumber(...) factory helpers for the raw table cell objects, mirroring the plainText / markdownText DSL (configurator overload plus a convenience overload). Gives callers an ergonomic way to build data_table / table cells without the raw builder. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
…Text Use the BlockCompositions.rawText(...) helper for the raw_text cells instead of RawTextObject.builder(), per the block-kit AGENTS.md guidance to build composition objects through BlockCompositions.* rather than raw builders. Depends on the rawText/rawNumber helpers added in slackapi/java-slack-sdk#1613. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
RawNumberObject.value is a (nullable) Double; the two-arg rawNumber convenience overload took a primitive double, narrowing the model's type. Use Double so the helper mirrors the field exactly. Co-Authored-By: Claude <svc-devxp-claude@slack-corp.com>
zimeg
left a comment
There was a problem hiding this comment.
☕ Ideas to share where included I callout a pattern I'm uncertain of around rawText and rawNumber!
There was a problem hiding this comment.
🦠 note: I have some confidence this is a consistent shared type but it's not clear if it's meant to be stable because it's not in reference. Hoping to add this here and #1611 for shared implementation!
| .registerTypeAdapter(ContextActionsBlockElement.class, new GsonContextActionsBlockElementFactory(failOnUnknownProps)) | ||
| .registerTypeAdapter(BlockElement.class, new GsonBlockElementFactory(failOnUnknownProps)) | ||
| .registerTypeAdapter(RichTextElement.class, new GsonRichTextElementFactory(failOnUnknownProps)) | ||
| .registerTypeAdapter(TableCell.class, new GsonTableCellFactory(failOnUnknownProps)) |
There was a problem hiding this comment.
📢 note: Here we add custom deserialization to handle the various type possibilities of the table cell.
| // RawNumberObject | ||
|
|
||
| public static RawNumberObject rawNumber(ModelConfigurator<RawNumberObject.RawNumberObjectBuilder> configurator) { | ||
| return configurator.configure(RawNumberObject.builder()).build(); | ||
| } | ||
|
|
||
| public static RawNumberObject rawNumber(Double value, String text) { | ||
| return RawNumberObject.builder().value(value).text(text).build(); | ||
| } |
There was a problem hiding this comment.
👁️🗨️ note: These introduce helper functions to BlockComposition that aren't documented but IMHO are helpful for:
- RawTextObject.builder().text("Name").build()
+ BlockCompositions.rawText("Name"),
Summary
Adds the new
data_tableBlock Kit layout block to the Java SDK model. The block displays rich tables that support pagination, sorting, filtering, and interactivity, where each row is a list of cells (raw_text,raw_number, orrich_text).What's included:
DataTableBlock(typedata_table) withrows,caption,pageSize,rowHeaderColumnIndex, andblockId.TableCellcell model incom.slack.api.model.block.composition:RawTextTableCell(raw_text),RawNumberTableCell(raw_number), andRichTextBlock(rich_text, which now implementsTableCell).DataTableBlock.rowsisList<List<TableCell>>.GsonTableCellFactoryto deserialize cells bytype, registered forTableCellin both the clientGsonFactoryand the model test factory.DataTableBlockregistered inGsonLayoutBlockFactory.Blocks.dataTable(...)builder DSL entry.Field javadoc mirrors the data-table-block reference Fields table verbatim, kept in sync with the corresponding node SDK PR (slackapi/node-slack-sdk#2638) after its review.
Shared cell model with the
tableblockThe
data_tablecells are the sameraw_text/raw_number/rich_textcell model thetableblock uses, so this PR uses the sharedTableCellfamily (interface +RawTextTableCell/RawNumberTableCellin...block.composition, deserialized by a singleGsonTableCellFactory) rather than a paralleldata_table-only set. This is the same cell model the siblingtable-block PR #1611 introduces — identical definitions, same package — so the two are aligned by construction: whichever lands second drops the now-duplicate cell files in a trivial merge. No behavioral reconciliation needed. (Mirrors node and python, which likewise share one cell model across both blocks — node's@slack/typescomposition objects, python'sslack_sdk.models.blocks.basic_components.)Reference
Schema: https://docs.slack.dev/reference/block-kit/blocks/data-table-block
Validation
Run in the touched modules (against latest
mainmerged in):./mvnw -pl slack-api-model -am test -Dtest=BlockKitTest -Djacoco.skip=true— Tests run: 57, Failures: 0, Errors: 0. IncludesparseDataTableBlock(deserialization of all three cell types +page_size/row_header_column_index) andbuildDataTableBlock(builder DSL + round-trip serialization)../mvnw -pl slack-api-client -am test-compile -Djacoco.skip=true— BUILD SUCCESS (verifies theGsonFactorychange in the client module compiles).Note:
jacoco.skip=truewas required because the locally available JDK is 25 and the pinned JaCoCo agent (0.8.7) cannot instrument class file major version 69. This is an environment limitation unrelated to the change; the surefire test execution itself passes. CI runs the JDK 8/14/17 matrix, where JaCoCo is unaffected.This repo does not use changesets (Maven multi-module project), so no changeset was added.
Co-Authored-By: Claude svc-devxp-claude@slack-corp.com