diff --git a/README.md b/README.md index 2d5ca524..9520d4c3 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,9 @@ var complexFiler = new CompoundFilter( - [x] Retrieve a page - [x] Create a page - [x] Update page -- [ ] Blocks +- [x] Blocks - [x] Retrieve a block - - [ ] Update a block + - [x] Update a block - [x] Retrieve block children - [x] Append block children - [x] Users diff --git a/Src/Notion.Client/Api/ApiEndpoints.cs b/Src/Notion.Client/Api/ApiEndpoints.cs index 942416fe..e2fa13cf 100644 --- a/Src/Notion.Client/Api/ApiEndpoints.cs +++ b/Src/Notion.Client/Api/ApiEndpoints.cs @@ -20,6 +20,7 @@ public static class UsersApiUrls public static class BlocksApiUrls { public static string Retrieve(string blockId) => $"/v1/blocks/{blockId}"; + public static string Update(string blockId) => $"/v1/blocks/{blockId}"; public static string RetrieveChildren(string blockId) => $"/v1/blocks/{blockId}/children"; public static string AppendChildren(string blockId) => $"/v1/blocks/{blockId}/children"; } diff --git a/Src/Notion.Client/Api/Blocks/BlocksClient.cs b/Src/Notion.Client/Api/Blocks/BlocksClient.cs index 9d74ad17..79f7da4d 100644 --- a/Src/Notion.Client/Api/Blocks/BlocksClient.cs +++ b/Src/Notion.Client/Api/Blocks/BlocksClient.cs @@ -48,7 +48,7 @@ public async Task AppendChildrenAsync(string blockId, BlocksAppendChildre return await _client.PatchAsync(url, body); } - public async Task Retrieve(string blockId) + public async Task RetrieveAsync(string blockId) { if (string.IsNullOrWhiteSpace(blockId)) { @@ -59,5 +59,17 @@ public async Task Retrieve(string blockId) return await _client.GetAsync(url); } + + public async Task UpdateAsync(string blockId, IUpdateBlock updateBlock) + { + if (string.IsNullOrWhiteSpace(blockId)) + { + throw new ArgumentNullException(nameof(blockId)); + } + + var url = BlocksApiUrls.Update(blockId); + + return await _client.PatchAsync(url, updateBlock); + } } } diff --git a/Src/Notion.Client/Api/Blocks/IBlocksClient.cs b/Src/Notion.Client/Api/Blocks/IBlocksClient.cs index 6ec10951..9d555c0c 100644 --- a/Src/Notion.Client/Api/Blocks/IBlocksClient.cs +++ b/Src/Notion.Client/Api/Blocks/IBlocksClient.cs @@ -9,7 +9,15 @@ public interface IBlocksClient /// /// /// Block - Task Retrieve(string blockId); + Task RetrieveAsync(string blockId); + + /// + /// Updates the content for the specified block_id based on the block type. + /// + /// + /// + /// Block + Task UpdateAsync(string blockId, IUpdateBlock updateBlock); Task> RetrieveChildrenAsync(string blockId, BlocksRetrieveChildrenParameters parameters = null); Task AppendChildrenAsync(string blockId, BlocksAppendChildrenParameters parameters = null); diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/BulletedListItemBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/BulletedListItemBlock.cs new file mode 100644 index 00000000..da4ad68d --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/BulletedListItemBlock.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class BulletedListItemUpdateBlock : IUpdateBlock + { + [JsonProperty("bulleted_list_item")] + public TextContentUpdate BulletedListItem { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingOneBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingOneBlock.cs new file mode 100644 index 00000000..65c166ad --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingOneBlock.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class HeadingOneUpdateBlock : IUpdateBlock + { + [JsonProperty("heading_1")] + public TextContentUpdate Heading_1 { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingThreeeBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingThreeeBlock.cs new file mode 100644 index 00000000..a562391e --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingThreeeBlock.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class HeadingThreeeUpdateBlock : IUpdateBlock + { + [JsonProperty("heading_3")] + public TextContentUpdate Heading_3 { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingTwoBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingTwoBlock.cs new file mode 100644 index 00000000..8e2a2bbd --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/HeadingTwoBlock.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class HeadingTwoUpdateBlock : IUpdateBlock + { + [JsonProperty("heading_2")] + public TextContentUpdate Heading_2 { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/IUpdateBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/IUpdateBlock.cs new file mode 100644 index 00000000..c28bcf62 --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/IUpdateBlock.cs @@ -0,0 +1,6 @@ +namespace Notion.Client +{ + public interface IUpdateBlock + { + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/NumberedListItemBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/NumberedListItemBlock.cs new file mode 100644 index 00000000..a63ed38d --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/NumberedListItemBlock.cs @@ -0,0 +1,10 @@ +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class NumberedListItemUpdateBlock : IUpdateBlock + { + [JsonProperty("numbered_list_item")] + public TextContentUpdate NumberedListItem { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ParagraphBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ParagraphBlock.cs new file mode 100644 index 00000000..42d103e6 --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ParagraphBlock.cs @@ -0,0 +1,7 @@ +namespace Notion.Client +{ + public class ParagraphUpdateBlock : IUpdateBlock + { + public TextContentUpdate Paragraph { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/TextContentUpdate.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/TextContentUpdate.cs new file mode 100644 index 00000000..b78f8fbf --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/TextContentUpdate.cs @@ -0,0 +1,9 @@ +using System.Collections.Generic; + +namespace Notion.Client +{ + public class TextContentUpdate + { + public IEnumerable Text { get; set; } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ToDoBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ToDoBlock.cs new file mode 100644 index 00000000..43b24863 --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ToDoBlock.cs @@ -0,0 +1,19 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Notion.Client +{ + public class ToDoUpdateBlock : IUpdateBlock + { + [JsonProperty("to_do")] + public Info ToDo { get; set; } + + public class Info + { + public IEnumerable Text { get; set; } + + [JsonProperty("checked")] + public bool IsChecked { get; set; } + } + } +} diff --git a/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ToggleBlock.cs b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ToggleBlock.cs new file mode 100644 index 00000000..e7027add --- /dev/null +++ b/Src/Notion.Client/Api/Blocks/RequestParams/BlocksUpdateParameters/UpdateBlocks/ToggleBlock.cs @@ -0,0 +1,7 @@ +namespace Notion.Client +{ + public class ToggleUpdateBlock : IUpdateBlock + { + public TextContentUpdate Toggle { get; set; } + } +} diff --git a/Test/Notion.UnitTests/BlocksClientTests.cs b/Test/Notion.UnitTests/BlocksClientTests.cs index d86c7ec3..e7bc01bd 100644 --- a/Test/Notion.UnitTests/BlocksClientTests.cs +++ b/Test/Notion.UnitTests/BlocksClientTests.cs @@ -75,7 +75,51 @@ public async Task RetrieveAsync() .WithBody(jsonData) ); - var block = await _client.Retrieve(blockId); + var block = await _client.RetrieveAsync(blockId); + + block.Id.Should().Be(blockId); + block.HasChildren.Should().BeFalse(); + block.Type.Should().Be(BlockType.ToDo); + + var todoBlock = ((ToDoBlock)block); + todoBlock.ToDo.Text.Should().ContainSingle(); + todoBlock.ToDo.Text.First().Should().BeAssignableTo(); + ((RichTextText)todoBlock.ToDo.Text.First()).Text.Content.Should().Be("Lacinato kale"); + } + + [Fact] + public async Task UpdateAsync() + { + string blockId = "9bc30ad4-9373-46a5-84ab-0a7845ee52e6"; + var path = ApiEndpoints.BlocksApiUrls.Update(blockId); + var jsonData = await File.ReadAllTextAsync("data/blocks/UpdateBlockResponse.json"); + + Server.Given(CreatePatchRequestBuilder(path)) + .RespondWith( + Response.Create() + .WithStatusCode(200) + .WithBody(jsonData) + ); + + var updateBlock = new ToDoUpdateBlock + { + ToDo = new ToDoUpdateBlock.Info + { + Text = new List() + { + new RichTextTextInput + { + Text = new Text + { + Content = "Lacinato kale" + }, + } + }, + IsChecked = true + } + }; + + var block = await _client.UpdateAsync(blockId, updateBlock); block.Id.Should().Be(blockId); block.HasChildren.Should().BeFalse(); diff --git a/Test/Notion.UnitTests/Notion.UnitTests.csproj b/Test/Notion.UnitTests/Notion.UnitTests.csproj index 81222651..a9b58659 100644 --- a/Test/Notion.UnitTests/Notion.UnitTests.csproj +++ b/Test/Notion.UnitTests/Notion.UnitTests.csproj @@ -30,6 +30,9 @@ Always + + Always + Always diff --git a/Test/Notion.UnitTests/data/blocks/UpdateBlockResponse.json b/Test/Notion.UnitTests/data/blocks/UpdateBlockResponse.json new file mode 100644 index 00000000..c9fb6a9a --- /dev/null +++ b/Test/Notion.UnitTests/data/blocks/UpdateBlockResponse.json @@ -0,0 +1,30 @@ +{ + "object": "block", + "id": "9bc30ad4-9373-46a5-84ab-0a7845ee52e6", + "created_time": "2021-03-16T16:31:00.000Z", + "last_edited_time": "2021-03-16T16:32:00.000Z", + "has_children": false, + "type": "to_do", + "to_do": { + "text": [ + { + "type": "text", + "text": { + "content": "Lacinato kale", + "link": null + }, + "annotations": { + "bold": false, + "italic": false, + "strikethrough": false, + "underline": false, + "code": false, + "color": "default" + }, + "plain_text": "Lacinato kale", + "href": null + } + ], + "checked": false + } +} \ No newline at end of file diff --git a/docs/README.md b/docs/README.md index 1e94a60f..b25583b8 100644 --- a/docs/README.md +++ b/docs/README.md @@ -73,9 +73,9 @@ var complexFiler = new CompoundFilter( - [x] Retrieve a page - [x] Create a page - [x] Update page -- [ ] Blocks +- [x] Blocks - [x] Retrieve a block - - [ ] Update a block + - [x] Update a block - [x] Retrieve block children - [x] Append block children - [x] Users