Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions block-kit/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Read the [docs](https://docs.slack.dev/block-kit/) to learn concepts behind thes
- **[Actions](https://docs.slack.dev/reference/block-kit/blocks/actions-block)**: Holds multiple interactive elements. [Implementation](./src/blocks/actions.py).
- **[Context](https://docs.slack.dev/reference/block-kit/blocks/context-block)**: Provides contextual info, which can include both images and text. [Implementation](./src/blocks/context.py).
- **[Context actions](https://docs.slack.dev/reference/block-kit/blocks/context-actions-block)**: Displays actions as contextual info, which can include both feedback buttons and icon buttons. [Implementation](./src/blocks/context_actions.py).
- **[Data visualization](https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block)**: Displays data using a line, bar, area, or pie chart. [Implementation](./src/blocks/data_visualization.py).
- **[Divider](https://docs.slack.dev/reference/block-kit/blocks/divider-block)**: Visually separates pieces of info inside of a message. [Implementation](./src/blocks/divider.py).
- **[File](https://docs.slack.dev/reference/block-kit/blocks/file-block)**: Displays info about remote files. [Implementation](./src/blocks/file.py).
- **[Header](https://docs.slack.dev/reference/block-kit/blocks/header-block)**: Displays a larger-sized text. [Implementation](./src/blocks/header.py).
Expand Down
142 changes: 142 additions & 0 deletions block-kit/src/blocks/data_visualization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from typing import Any, Dict, Optional, Set

from slack_sdk.models.blocks import Block


class DataVisualizationBlock(Block):
"""Displays data using a line, bar, area, or pie chart.
https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block

The slack_sdk does not yet ship a typed class for this block, so this
example defines one that mirrors the SDK convention.
"""

type = "data_visualization"

@property
def attributes(self) -> Set[str]: # type: ignore[override]
return super().attributes.union({"title", "chart"})

def __init__(
self,
*,
title: str,
chart: Dict[str, Any],
block_id: Optional[str] = None,
) -> None:
"""
Args:
title (required): A label describing the chart. Maximum 50 characters.
chart (required): The chart payload. The type must be one of pie, bar,
area, or line. Pie charts use a segments array, while bar, area, and
line charts use a series array alongside an axis_config object.
block_id: A unique identifier for a block. If not specified, a block_id
will be generated. Maximum length for this field is 255 characters.
"""
super().__init__(type=self.type, block_id=block_id)
self.title = title
self.chart = chart


def example01() -> DataVisualizationBlock:
"""
Displays data using a pie chart.
https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block/

A pie chart with labeled segments.
"""
block = DataVisualizationBlock(
title="My Favorite Candy Bars",
chart={
"type": "pie",
"segments": [
{"label": "Kit Kat", "value": 45},
{"label": "Twix", "value": 28},
{"label": "Crunch", "value": 18},
{"label": "Milky Way", "value": 9},
],
},
)
return block


def example02() -> DataVisualizationBlock:
"""
Displays data using a bar chart.
https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block/

A bar chart with a single series and axis configuration.
"""
block = DataVisualizationBlock(
title="My Favorite Pies by Percentage of Tastiness",
chart={
"type": "bar",
"series": [
{
"name": "Pies",
"data": [
{"label": "Strawberry Rhubarb", "value": 85},
{"label": "Pumpkin", "value": 70},
{"label": "Lemon Meringue", "value": 72},
{"label": "Blueberry", "value": 90},
{"label": "Key Lime", "value": 56},
],
}
],
"axis_config": {
"categories": [
"Strawberry Rhubarb",
"Pumpkin",
"Lemon Meringue",
"Blueberry",
"Key Lime",
],
"x_label": "Pies",
"y_label": "Percentage of Tastiness",
},
},
)
return block


def example03() -> DataVisualizationBlock:
"""
Displays data using a line chart.
https://docs.slack.dev/reference/block-kit/blocks/data-visualization-block/

A line chart comparing multiple series over time.
"""
block = DataVisualizationBlock(
title="Weekly Paper Sales",
chart={
"type": "line",
"series": [
{
"name": "Dunder Mifflin Infinity Website",
"data": [
{"label": "Week 1", "value": 32000},
{"label": "Week 2", "value": 35000},
{"label": "Week 3", "value": 29000},
{"label": "Week 4", "value": 41000},
{"label": "Week 5", "value": 45000},
],
},
{
"name": "Dunder Mifflin In-store",
"data": [
{"label": "Week 1", "value": 18000},
{"label": "Week 2", "value": 21000},
{"label": "Week 3", "value": 24000},
{"label": "Week 4", "value": 22000},
{"label": "Week 5", "value": 26000},
],
},
],
"axis_config": {
"categories": ["Week 1", "Week 2", "Week 3", "Week 4", "Week 5"],
"x_label": "Week",
"y_label": "Paper Sales (USD)",
},
},
)
return block
98 changes: 98 additions & 0 deletions block-kit/tests/blocks/test_data_visualization.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import json

from src.blocks import data_visualization


def test_example01():
block = data_visualization.example01()
actual = block.to_dict()
expected = {
"type": "data_visualization",
"title": "My Favorite Candy Bars",
"chart": {
"type": "pie",
"segments": [
{"label": "Kit Kat", "value": 45},
{"label": "Twix", "value": 28},
{"label": "Crunch", "value": 18},
{"label": "Milky Way", "value": 9},
],
},
}
assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True)


def test_example02():
block = data_visualization.example02()
actual = block.to_dict()
expected = {
"type": "data_visualization",
"title": "My Favorite Pies by Percentage of Tastiness",
"chart": {
"type": "bar",
"series": [
{
"name": "Pies",
"data": [
{"label": "Strawberry Rhubarb", "value": 85},
{"label": "Pumpkin", "value": 70},
{"label": "Lemon Meringue", "value": 72},
{"label": "Blueberry", "value": 90},
{"label": "Key Lime", "value": 56},
],
}
],
"axis_config": {
"categories": [
"Strawberry Rhubarb",
"Pumpkin",
"Lemon Meringue",
"Blueberry",
"Key Lime",
],
"x_label": "Pies",
"y_label": "Percentage of Tastiness",
},
},
}
assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True)


def test_example03():
block = data_visualization.example03()
actual = block.to_dict()
expected = {
"type": "data_visualization",
"title": "Weekly Paper Sales",
"chart": {
"type": "line",
"series": [
{
"name": "Dunder Mifflin Infinity Website",
"data": [
{"label": "Week 1", "value": 32000},
{"label": "Week 2", "value": 35000},
{"label": "Week 3", "value": 29000},
{"label": "Week 4", "value": 41000},
{"label": "Week 5", "value": 45000},
],
},
{
"name": "Dunder Mifflin In-store",
"data": [
{"label": "Week 1", "value": 18000},
{"label": "Week 2", "value": 21000},
{"label": "Week 3", "value": 24000},
{"label": "Week 4", "value": 22000},
{"label": "Week 5", "value": 26000},
],
},
],
"axis_config": {
"categories": ["Week 1", "Week 2", "Week 3", "Week 4", "Week 5"],
"x_label": "Week",
"y_label": "Paper Sales (USD)",
},
},
}
assert json.dumps(actual, sort_keys=True) == json.dumps(expected, sort_keys=True)