Skip to content

Commit 60d4a95

Browse files
authored
Add workflow_button block element (#1399)
1 parent d468b35 commit 60d4a95

File tree

4 files changed

+143
-1
lines changed

4 files changed

+143
-1
lines changed

slack_sdk/models/blocks/basic_components.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,3 +524,38 @@ def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
524524
if self._trigger_actions_on:
525525
json["trigger_actions_on"] = self._trigger_actions_on
526526
return json
527+
528+
529+
class WorkflowTrigger(JsonObject):
530+
attributes = {"trigger"}
531+
532+
def __init__(self, *, url: str, customizable_input_parameters: Optional[List[Dict[str, str]]] = None):
533+
self._url = url
534+
self._customizable_input_parameters = customizable_input_parameters
535+
536+
def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
537+
self.validate_json()
538+
json = {"url": self._url}
539+
if self._customizable_input_parameters is not None:
540+
json.update({"customizable_input_parameters": self._customizable_input_parameters})
541+
return json
542+
543+
544+
class Workflow(JsonObject):
545+
attributes = {"trigger"}
546+
547+
def __init__(
548+
self,
549+
*,
550+
trigger: Union[WorkflowTrigger, dict],
551+
):
552+
self._trigger = trigger
553+
554+
def to_dict(self) -> Dict[str, Any]: # skipcq: PYL-W0221
555+
self.validate_json()
556+
json = {}
557+
if isinstance(self._trigger, WorkflowTrigger):
558+
json["trigger"] = self._trigger.to_dict()
559+
else:
560+
json["trigger"] = self._trigger
561+
return json

slack_sdk/models/blocks/block_elements.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
JsonValidator,
1212
EnumValidator,
1313
)
14-
from .basic_components import ButtonStyles
14+
from .basic_components import ButtonStyles, Workflow
1515
from .basic_components import ConfirmObject
1616
from .basic_components import DispatchActionConfig
1717
from .basic_components import MarkdownTextObject
@@ -1689,3 +1689,60 @@ def __init__(
16891689
@JsonValidator(f"options attribute must have between {options_min_length} " f"and {options_max_length} items")
16901690
def _validate_options_length(self) -> bool:
16911691
return self.options_min_length <= len(self.options) <= self.options_max_length
1692+
1693+
1694+
# -------------------------------------------------
1695+
# Workflow Button
1696+
# -------------------------------------------------
1697+
1698+
1699+
class WorkflowButtonElement(InteractiveElement):
1700+
type = "workflow_button"
1701+
1702+
@property
1703+
def attributes(self) -> Set[str]:
1704+
return super().attributes.union({"text", "workflow", "style", "accessibility_label"})
1705+
1706+
def __init__(
1707+
self,
1708+
*,
1709+
text: Union[str, dict, TextObject],
1710+
action_id: Optional[str] = None,
1711+
workflow: Optional[Union[dict, Workflow]] = None,
1712+
style: Optional[str] = None, # primary, danger
1713+
accessibility_label: Optional[str] = None,
1714+
**others: dict,
1715+
):
1716+
"""Allows users to run a link trigger with customizable inputs
1717+
Interactive component - but interactions with workflow button elements will not send block_actions events,
1718+
since these are used to start new workflow runs.
1719+
https://api.slack.com/reference/block-kit/block-elements#workflow_button
1720+
1721+
Args:
1722+
text (required): A text object that defines the button's text.
1723+
Can only be of type: plain_text. text may truncate with ~30 characters.
1724+
Maximum length for the text in this field is 75 characters.
1725+
action_id (required): An identifier for this action.
1726+
You can use this when you receive an interaction payload to identify the source of the action.
1727+
Should be unique among all other action_ids in the containing block.
1728+
Maximum length for this field is 255 characters.
1729+
workflow: A workflow object that contains details about the workflow
1730+
that will run when the button is clicked.
1731+
style: Decorates buttons with alternative visual color schemes. Use this option with restraint.
1732+
"primary" gives buttons a green outline and text, ideal for affirmation or confirmation actions.
1733+
"primary" should only be used for one button within a set.
1734+
"danger" gives buttons a red outline and text, and should be used when the action is destructive.
1735+
Use "danger" even more sparingly than "primary".
1736+
If you don't include this field, the default button style will be used.
1737+
accessibility_label: A label for longer descriptive text about a button element.
1738+
This label will be read out by screen readers instead of the button text object.
1739+
Maximum length for this field is 75 characters.
1740+
"""
1741+
super().__init__(action_id=action_id, type=self.type)
1742+
show_unknown_key_warning(self, others)
1743+
1744+
# NOTE: default_type=PlainTextObject.type here is only for backward-compatibility with version 2.5.0
1745+
self.text = TextObject.parse(text, default_type=PlainTextObject.type)
1746+
self.workflow = workflow
1747+
self.style = style
1748+
self.accessibility_label = accessibility_label

tests/slack_sdk/models/test_elements.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
EmailInputElement,
3434
NumberInputElement,
3535
UrlInputElement,
36+
WorkflowButtonElement,
3637
)
3738
from . import STRING_3001_CHARS, STRING_301_CHARS
3839

@@ -1213,3 +1214,26 @@ def test_focus_on_load(self):
12131214
"focus_on_load": True,
12141215
}
12151216
self.assertDictEqual(input, RadioButtonsElement(**input).to_dict())
1217+
1218+
1219+
# -------------------------------------------------
1220+
# Workflow Button
1221+
# -------------------------------------------------
1222+
1223+
1224+
class WorkflowButtonElementTests(unittest.TestCase):
1225+
def test_load(self):
1226+
input = {
1227+
"type": "workflow_button",
1228+
"text": {"type": "plain_text", "text": "Run Workflow"},
1229+
"workflow": {
1230+
"trigger": {
1231+
"url": "https://slack.com/shortcuts/Ft0123ABC456/xyz...zyx",
1232+
"customizable_input_parameters": [
1233+
{"name": "input_parameter_a", "value": "Value for input param A"},
1234+
{"name": "input_parameter_b", "value": "Value for input param B"},
1235+
],
1236+
}
1237+
},
1238+
}
1239+
self.assertDictEqual(input, WorkflowButtonElement(**input).to_dict())

tests/slack_sdk/models/test_objects.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
OptionGroup,
1212
PlainTextObject,
1313
)
14+
from slack_sdk.models.blocks.basic_components import Workflow, WorkflowTrigger
1415
from slack_sdk.models.messages import (
1516
ChannelLink,
1617
DateLink,
@@ -566,3 +567,28 @@ def test_confirm_style_validation(self):
566567
"style": "something-wrong",
567568
}
568569
).validate_json()
570+
571+
572+
class WorkflowTests(unittest.TestCase):
573+
def test_creation(self):
574+
workflow = Workflow(
575+
trigger=WorkflowTrigger(
576+
url="https://slack.com/shortcuts/Ft0123ABC456/xyz...zyx",
577+
customizable_input_parameters=[
578+
{"name": "input_parameter_a", "value": "Value for input param A"},
579+
{"name": "input_parameter_b", "value": "Value for input param B"},
580+
],
581+
)
582+
)
583+
self.assertDictEqual(
584+
workflow.to_dict(),
585+
{
586+
"trigger": {
587+
"url": "https://slack.com/shortcuts/Ft0123ABC456/xyz...zyx",
588+
"customizable_input_parameters": [
589+
{"name": "input_parameter_a", "value": "Value for input param A"},
590+
{"name": "input_parameter_b", "value": "Value for input param B"},
591+
],
592+
}
593+
},
594+
)

0 commit comments

Comments
 (0)