Skip to content

Commit 35d8ee3

Browse files
committed
Add Steps from Apps (no tests, WIP)
1 parent 1f3f4ac commit 35d8ee3

21 files changed

+1166
-244
lines changed

samples/async_steps_from_apps.py

Lines changed: 118 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
from slack_sdk.web.async_client import AsyncSlackResponse, AsyncWebClient
1111
from slack_bolt.async_app import AsyncApp, AsyncAck
12+
from slack_bolt.workflows.step.async_step import AsyncConfigure, AsyncUpdate, AsyncComplete, AsyncFail
1213

1314
logging.basicConfig(level=logging.DEBUG)
1415

@@ -20,153 +21,149 @@
2021
# https://api.slack.com/tutorials/workflow-builder-steps
2122

2223

23-
@app.action({"type": "workflow_step_edit", "callback_id": "copy_review"})
24-
async def edit(body: dict, ack: AsyncAck, client: AsyncWebClient):
24+
async def edit(ack: AsyncAck, configure: AsyncConfigure):
2525
await ack()
26-
new_modal: AsyncSlackResponse = await client.views_open(
27-
trigger_id=body["trigger_id"],
28-
view={
29-
"type": "workflow_step",
30-
"callback_id": "copy_review_view",
31-
"blocks": [
32-
{
33-
"type": "section",
34-
"block_id": "intro-section",
35-
"text": {
36-
"type": "plain_text",
37-
"text": "Create a task in one of the listed projects. The link to the task and other details will be available as variable data in later steps.",
38-
},
26+
await configure(
27+
blocks=[
28+
{
29+
"type": "section",
30+
"block_id": "intro-section",
31+
"text": {
32+
"type": "plain_text",
33+
"text": "Create a task in one of the listed projects. The link to the task and other details will be available as variable data in later steps.",
3934
},
40-
{
41-
"type": "input",
42-
"block_id": "task_name_input",
43-
"element": {
44-
"type": "plain_text_input",
45-
"action_id": "task_name",
46-
"placeholder": {
47-
"type": "plain_text",
48-
"text": "Write a task name",
49-
},
35+
},
36+
{
37+
"type": "input",
38+
"block_id": "task_name_input",
39+
"element": {
40+
"type": "plain_text_input",
41+
"action_id": "task_name",
42+
"placeholder": {
43+
"type": "plain_text",
44+
"text": "Write a task name",
5045
},
51-
"label": {"type": "plain_text", "text": "Task name"},
5246
},
53-
{
54-
"type": "input",
55-
"block_id": "task_description_input",
56-
"element": {
57-
"type": "plain_text_input",
58-
"action_id": "task_description",
59-
"placeholder": {
60-
"type": "plain_text",
61-
"text": "Write a description for your task",
62-
},
47+
"label": {"type": "plain_text", "text": "Task name"},
48+
},
49+
{
50+
"type": "input",
51+
"block_id": "task_description_input",
52+
"element": {
53+
"type": "plain_text_input",
54+
"action_id": "task_description",
55+
"placeholder": {
56+
"type": "plain_text",
57+
"text": "Write a description for your task",
6358
},
64-
"label": {"type": "plain_text", "text": "Task description"},
6559
},
66-
{
67-
"type": "input",
68-
"block_id": "task_author_input",
69-
"element": {
70-
"type": "plain_text_input",
71-
"action_id": "task_author",
72-
"placeholder": {
73-
"type": "plain_text",
74-
"text": "Write a task name",
75-
},
60+
"label": {"type": "plain_text", "text": "Task description"},
61+
},
62+
{
63+
"type": "input",
64+
"block_id": "task_author_input",
65+
"element": {
66+
"type": "plain_text_input",
67+
"action_id": "task_author",
68+
"placeholder": {
69+
"type": "plain_text",
70+
"text": "Write a task name",
7671
},
77-
"label": {"type": "plain_text", "text": "Task author"},
7872
},
79-
],
80-
},
73+
"label": {"type": "plain_text", "text": "Task author"},
74+
},
75+
]
8176
)
8277

8378

84-
@app.view("copy_review_view")
85-
async def save(ack: AsyncAck, client: AsyncWebClient, body: dict):
79+
async def save(ack: AsyncAck, body: dict, update: AsyncUpdate):
8680
state_values = body["view"]["state"]["values"]
87-
response: AsyncSlackResponse = await client.api_call(
88-
api_method="workflows.updateStep",
89-
json={
90-
"workflow_step_edit_id": body["workflow_step"]["workflow_step_edit_id"],
91-
"inputs": {
92-
"taskName": {
93-
"value": state_values["task_name_input"]["task_name"]["value"],
94-
},
95-
"taskDescription": {
96-
"value": state_values["task_description_input"]["task_description"][
97-
"value"
98-
],
99-
},
100-
"taskAuthorEmail": {
101-
"value": state_values["task_author_input"]["task_author"]["value"],
102-
},
81+
await update(
82+
inputs={
83+
"taskName": {
84+
"value": state_values["task_name_input"]["task_name"]["value"],
85+
},
86+
"taskDescription": {
87+
"value": state_values["task_description_input"]["task_description"][
88+
"value"
89+
],
90+
},
91+
"taskAuthorEmail": {
92+
"value": state_values["task_author_input"]["task_author"]["value"],
10393
},
104-
"outputs": [
105-
{"name": "taskName", "type": "text", "label": "Task Name",},
106-
{
107-
"name": "taskDescription",
108-
"type": "text",
109-
"label": "Task Description",
110-
},
111-
{
112-
"name": "taskAuthorEmail",
113-
"type": "text",
114-
"label": "Task Author Email",
115-
},
116-
],
11794
},
95+
outputs=[
96+
{"name": "taskName", "type": "text", "label": "Task Name", },
97+
{
98+
"name": "taskDescription",
99+
"type": "text",
100+
"label": "Task Description",
101+
},
102+
{
103+
"name": "taskAuthorEmail",
104+
"type": "text",
105+
"label": "Task Author Email",
106+
},
107+
]
118108
)
119109
await ack()
120110

121111

122112
pseudo_database = {}
123113

124114

125-
@app.event("workflow_step_execute")
126-
async def execute(body: dict, client: AsyncWebClient):
127-
step = body["event"]["workflow_step"]
128-
completion: AsyncSlackResponse = await client.api_call(
129-
api_method="workflows.stepCompleted",
130-
json={
131-
"workflow_step_execute_id": step["workflow_step_execute_id"],
132-
"outputs": {
115+
async def execute(body: dict, client: AsyncWebClient, complete: AsyncComplete, fail: AsyncFail):
116+
try:
117+
step = body["event"]["workflow_step"]
118+
await complete(
119+
outputs={
133120
"taskName": step["inputs"]["taskName"]["value"],
134121
"taskDescription": step["inputs"]["taskDescription"]["value"],
135122
"taskAuthorEmail": step["inputs"]["taskAuthorEmail"]["value"],
136-
},
137-
},
138-
)
139-
user: AsyncSlackResponse = await client.users_lookupByEmail(
140-
email=step["inputs"]["taskAuthorEmail"]["value"]
141-
)
142-
user_id = user["user"]["id"]
143-
new_task = {
144-
"task_name": step["inputs"]["taskName"]["value"],
145-
"task_description": step["inputs"]["taskDescription"]["value"],
146-
}
147-
tasks = pseudo_database.get(user_id, [])
148-
tasks.append(new_task)
149-
pseudo_database[user_id] = tasks
150-
151-
blocks = []
152-
for task in tasks:
153-
blocks.append(
154-
{
155-
"type": "section",
156-
"text": {"type": "plain_text", "text": task["task_name"]},
157123
}
158124
)
159-
blocks.append({"type": "divider"})
160-
161-
home_tab_update: AsyncSlackResponse = await client.views_publish(
162-
user_id=user_id,
163-
view={
164-
"type": "home",
165-
"title": {"type": "plain_text", "text": "Your tasks!"},
166-
"blocks": blocks,
167-
},
168-
)
169-
125+
user: AsyncSlackResponse = await client.users_lookupByEmail(
126+
email=step["inputs"]["taskAuthorEmail"]["value"]
127+
)
128+
user_id = user["user"]["id"]
129+
new_task = {
130+
"task_name": step["inputs"]["taskName"]["value"],
131+
"task_description": step["inputs"]["taskDescription"]["value"],
132+
}
133+
tasks = pseudo_database.get(user_id, [])
134+
tasks.append(new_task)
135+
pseudo_database[user_id] = tasks
136+
137+
blocks = []
138+
for task in tasks:
139+
blocks.append(
140+
{
141+
"type": "section",
142+
"text": {"type": "plain_text", "text": task["task_name"]},
143+
}
144+
)
145+
blocks.append({"type": "divider"})
146+
147+
home_tab_update: AsyncSlackResponse = await client.views_publish(
148+
user_id=user_id,
149+
view={
150+
"type": "home",
151+
"title": {"type": "plain_text", "text": "Your tasks!"},
152+
"blocks": blocks,
153+
},
154+
)
155+
except:
156+
await fail(error={
157+
"message": "Something wrong!"
158+
})
159+
160+
161+
app.step(
162+
callback_id="copy_review",
163+
edit=edit,
164+
save=save,
165+
execute=execute,
166+
)
170167

171168
if __name__ == "__main__":
172169
app.start(3000) # POST http://localhost:3000/slack/events

0 commit comments

Comments
 (0)