Skip to content

Commit f8fb5e2

Browse files
authored
Work Objects Support (#108)
* Update viewSubmissionPayload * Update unfurl request initial entity metadata (incomplete) * initial work on creating payload structure (broken) * tidy up payload entities * Fix field and post structure * Add edit options * Add entity presentDetails api * Add entity API and output format * Package bump
1 parent 7161924 commit f8fb5e2

71 files changed

Lines changed: 1369 additions & 60 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

Slack.NetStandard.Tests/EventsApiTests.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -542,5 +542,12 @@ public void AssistantThreadContextChanged()
542542
var result = Utility.AssertSubType<CallbackEvent, AssistantThreadContextChanged>("Events_AssistantThreadContextChanged.json");
543543
Assert.Null(result.OtherFields);
544544
}
545+
546+
[Fact]
547+
public void EntityDetailsRequested()
548+
{
549+
var result = Utility.AssertSubType<CallbackEvent, EntityDetailsRequested>("Events_EntityDetailsRequested.json");
550+
Assert.Null(result.OtherFields);
551+
}
545552
}
546553
}

Slack.NetStandard.Tests/Examples/BlockActionsPayload.json

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,8 +103,37 @@
103103
"text": "Action A",
104104
"emoji": true
105105
},
106-
"selected_users": ["U1234","U2345"],
106+
"selected_users": [ "U1234", "U2345" ],
107107
"action_ts": "1571318425.267782"
108108
}
109-
]
109+
],
110+
"app_unfurl": {
111+
"id": 1,
112+
"bot_id": "B123ABC456",
113+
"bot_team_id": "T123ABC456",
114+
"app_unfurl_url": "https://github.com/KrishnaPatel1/github-function-test/issues/139",
115+
"is_app_unfurl": true,
116+
"fallback": "Create Capybara login page\n Issue in GitHub",
117+
"text": "Issue in GitHub",
118+
"title": "Create Capybara login page",
119+
"title_link": "https://github.com/issues/139",
120+
"service_name": "Work Objects Demo App",
121+
"fields": [
122+
{
123+
"value": "open",
124+
"title": "Status",
125+
"short": true
126+
},
127+
{
128+
"value": "KrishnaPatel1",
129+
"title": "Assignee",
130+
"short": true
131+
},
132+
{
133+
"value": "FY26 Q2",
134+
"title": "Milestone",
135+
"short": true
136+
}
137+
]
138+
}
110139
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
{
2+
"type": "entity_details_requested",
3+
"user": "U0123456", // user who opened the flexpane
4+
"external_ref": {
5+
// `external_ref` that was set in the `metadata` of `chat.unfurl`.
6+
// This is not guaranteed to be set in all cases. For example,
7+
// when a work object is opened from an Enterprise Search result
8+
// provided by a Slack-developed search provider, we cannot provide
9+
// an `external_ref`.
10+
"id": "123",
11+
"type": "my-type" // optional
12+
},
13+
14+
// This is the URL that identifies the entity in the developer's system. In the entity metadata, this property is called `url`.
15+
"entity_url": "https://example.com/document/123",
16+
"link": {
17+
"url": "https://example.com/document/123",
18+
"domain": "example.com" // domain of the URL
19+
},
20+
// This is the exact URL that was unfurled in the Slack message. It could be the same as `entity_url`, or different.
21+
"app_unfurl_url": "https://example.com/document/123?myquery=param",
22+
23+
"event_ts": "123456789.1234566", // event timestamp
24+
"trigger_id": "1234567890123.1234567890123.abcdef01234567890abcdef012345689", // event trigger ID
25+
"user_locale": "en-US",
26+
27+
// These fields will not be provided when the entity details are opened
28+
// from outside of a message context (i.e., Enterprise Search)
29+
"channel": "C123ABC456", // ID of the channel where the source message was posted
30+
"message_ts": "1755035323.759739", // timestamp of the source message
31+
"thread_ts": "1755035323.759739" // timestamp of the root message, if the source message is part of a thread
32+
}
Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,54 @@
11
{
22
"type": "view_submission",
33
"team": {
4-
"id": "TXXXXXX",
5-
"domain": "coverbands"
4+
"id": "T123ABC456",
5+
"domain": "slack-domain-12343",
6+
"enterprise_id": "E1234",
7+
"enterprise_name": "Acme Corp"
68
},
79
"user": {
8-
"id": "UXXXXXX",
9-
"name": "dreamweaver"
10+
"id": "U1234",
11+
"username": "jennifer_hynes",
12+
"name": "jennifer_hynes",
13+
"team_id": "T123ABC456"
1014
},
15+
"api_app_id": "A123ABC456",
16+
"token": "vrv7tNLHMRT8hdqLZjuM10St",
17+
"trigger_id": "1234567890123.1234567890123.abcdef01234567890abcdef012345689",
1118
"view": {
12-
"id": "VNHU13V36",
13-
"type": "modal",
14-
"title": "Hello world",
15-
"submit": {
16-
"type": "plain_text",
17-
"text": "Title"
18-
},
19-
"private_metadata": "shhh-its-secret",
20-
"callback_id": "modal-with-inputs",
19+
"id": "V08UHA2RFFF",
20+
"team_id": "E123ABC456",
21+
"type": "entity_detail",
22+
"private_metadata": "",
23+
"callback_id": "",
2124
"state": {
2225
"values": {
23-
"question1": {
24-
"1ea72d25-5d37-405b-85b6-27eae722ac2c": {
25-
"type": "static_select",
26-
"selected_option": {
27-
"text": {
28-
"type": "plain_text",
29-
"text": "Anne+aBC",
30-
"emoji": true
31-
},
32-
"value": "U017E89XY33"
33-
}
34-
}
35-
},
36-
"multi-line": {
37-
"ml-value": {
26+
"description": {
27+
"description.input": {
3828
"type": "plain_text_input",
39-
"value": "This is my example inputted value"
40-
}
41-
},
42-
"user-select": {
43-
"select-user": {
44-
"type": "users_select",
45-
"selected_user": "U12345678"
29+
"value": "We need to implement a login page using **Capybara** for our testing framework. This page will be used for testing user authentication and login functionality within the application. hello\\n\\n### Requirements:\\n- Create a simple login page with fields for:\\n - **Username**\\n - **Password**\\n - **Login button**\\n- Implement basic form validation to ensure both fields are populated before submitting.\\n- Ensure the page is responsive and works well on both desktop and mobile views.\\n- Use **Capybara** to automate the interaction with the login form for testing purposes.\\n - Automate filling out the username and password fields.\\n - Simulate clicking the login button and validating the redirect or success message.\\n\\n![Image](https://github.com/user-attachments/assets/f94f0a80-993d-46c5-be4c-1d3f3cd8312d)"
4630
}
4731
}
4832
}
4933
},
50-
"hash": "156663117.cd33ad1f"
34+
"hash": "1748539925.7JuMmoCH",
35+
"external_ref": {
36+
"id": "139"
37+
},
38+
"entity_url": "https://github.com/repos/{user}/{repo}/issues/139",
39+
"message_ts": "1758902242.754879",
40+
"thread_ts": "1758901978.959789",
41+
"channel": "C123ABC456",
42+
"app_unfurl_url": "https://github.com/repos/{user}/{repo}/issues/139?myquery=param",
43+
"app_id": "A123ABC456",
44+
"external_id": "",
45+
"app_installed_team_id": "E123ABC456",
46+
"bot_id": "B0123456"
47+
},
48+
"response_urls": [],
49+
"is_enterprise_install": false,
50+
"enterprise": {
51+
"id": "E1234",
52+
"name": "Acme Corp"
5153
}
5254
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
{
2+
"trigger_id": "1234567890123.1234567890123.abcdef01234567890abcdef012345689",
3+
"error": {
4+
"status": "custom_partial_view",
5+
"custom_title": "Ruh roh",
6+
"custom_message": ":hand: This item is *restricted* per our [company policy](https://example.com). Don't worry though, you can request access using the button below.",
7+
"message_format": "markdown",
8+
"actions": [
9+
{
10+
"text": "Request access",
11+
"action_id": "request_access",
12+
"value": "some_val",
13+
"processing_state": {
14+
"enabled": true // This can be enabled to disable the button and show a loading state for up to 30 seconds or until your app responds with another call to the `entity.presentDetails` API method.
15+
}
16+
}
17+
]
18+
}
19+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
{
2+
"entity_type": "slack#/entities/task",
3+
"entity_payload": {
4+
"attributes": {
5+
"title": {
6+
"text": "Update links in login page",
7+
"edit": {
8+
"enabled": true
9+
// The title is always required (i.e., optional: false)
10+
}
11+
}
12+
},
13+
"fields": {
14+
"description": {
15+
"type": "string",
16+
"value": "We need to update the links in the login page to use our new branding",
17+
"edit": {
18+
"enabled": true,
19+
"text": {
20+
"min_length": 15
21+
}
22+
}
23+
}
24+
},
25+
"custom_fields": [
26+
{
27+
"key": "story_points",
28+
"label": "Story points",
29+
"type": "integer",
30+
"edit": {
31+
"enabled": true,
32+
"number": {
33+
"max_value": 10
34+
}
35+
}
36+
}
37+
]
38+
}
39+
}

Slack.NetStandard.Tests/InteractionTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public void ViewSubmissionPayload()
2020
var viewSubmissionPayload = Utility.AssertSubType<InteractionPayload, ViewSubmissionPayload>("ViewSubmissionPayload.json");
2121

2222
Assert.Null(viewSubmissionPayload.OtherFields);
23+
Assert.Null(viewSubmissionPayload.View.OtherFields);
2324
Assert.All(viewSubmissionPayload.View.State.Values.SelectMany(v => v.Value.Values),
2425
elementValue => Assert.Null(elementValue.OtherFields));
2526
}

Slack.NetStandard.Tests/Slack.NetStandard.Tests.csproj

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
</ItemGroup>
2121

2222
<ItemGroup>
23+
<None Update="Examples\WorkObjects_Task.json">
24+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
25+
</None>
2326
<None Update="Examples\Cells_Channel.json">
2427
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
2528
</None>
@@ -110,6 +113,9 @@
110113
<None Update="Examples\Events_AssistantThreadStarted.json">
111114
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
112115
</None>
116+
<None Update="Examples\Events_EntityDetailsRequested.json">
117+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
118+
</None>
113119
<None Update="Examples\Events_FunctionExecuted.json">
114120
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
115121
</None>
@@ -581,6 +587,9 @@
581587
<None Update="Examples\Web_ConversationGetTeams.json">
582588
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
583589
</None>
590+
<None Update="Examples\Web_EntityPresentDetails.json">
591+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
592+
</None>
584593
<None Update="Examples\Web_FilesCompleteExternal.json">
585594
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
586595
</None>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
using System.Collections.Generic;
2+
using System.Threading.Tasks;
3+
using Slack.NetStandard.Objects.WorkObjects;
4+
using Slack.NetStandard.WebApi.Entity;
5+
using Xunit;
6+
7+
namespace Slack.NetStandard.Tests
8+
{
9+
public class WebApiTests_Entity
10+
{
11+
[Fact]
12+
public async Task PresentDetails()
13+
{
14+
await Utility.AssertWebApi(c => c.Entity.PresentDetails(new PresentDetailsRequest
15+
{
16+
TriggerId = "1234567890123.1234567890123.abcdef01234567890abcdef012345689",
17+
Error = new EntityError
18+
{
19+
Status = EntityErrorStatus.CustomPartialView,
20+
CustomTitle = "Ruh roh",
21+
CustomMessage = ":hand: This item is *restricted* per our [company policy](https://example.com). Don't worry though, you can request access using the button below.",
22+
MessageFormat = "markdown",
23+
Actions = new List<EntityPayloadAction> {
24+
new EntityPayloadAction {
25+
Text = "Request access",
26+
ActionId = "request_access",
27+
Value = "some_val",
28+
ProcessingState = new ProcessingState{ Enabled = true }
29+
}
30+
}
31+
}
32+
}), "entity.presentDetails", jo => {
33+
Assert.True(Utility.CompareJson(jo, "Web_EntityPresentDetails.json"));
34+
});
35+
}
36+
}
37+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Slack.NetStandard.Objects.WorkObjects;
2+
using System.Threading.Tasks;
3+
using Xunit;
4+
5+
namespace Slack.NetStandard.Tests
6+
{
7+
public class WorkObjectTests
8+
{
9+
[Fact]
10+
public async Task TaskEntity()
11+
{
12+
Utility.AssertType<MetadataEntity>("WorkObjects_Task.json");
13+
}
14+
}
15+
}

0 commit comments

Comments
 (0)