diff --git a/src/Crowdin.Api/Tasks/ITasksApiExecutor.cs b/src/Crowdin.Api/Tasks/ITasksApiExecutor.cs index 54fcaaae..8af70ed6 100644 --- a/src/Crowdin.Api/Tasks/ITasksApiExecutor.cs +++ b/src/Crowdin.Api/Tasks/ITasksApiExecutor.cs @@ -19,6 +19,14 @@ Task> ListTasks( int? assigneeId = null, IEnumerable? orderBy = null); + Task> ListTasks( + int projectId, + int limit = 25, + int offset = 0, + IEnumerable? statuses = null, + int? assigneeId = null, + IEnumerable? orderBy = null); + Task> ListTasks(int projectId, TasksListParams @params); Task AddTask(int projectId, AddTaskRequest request); diff --git a/src/Crowdin.Api/Tasks/TasksApiExecutor.cs b/src/Crowdin.Api/Tasks/TasksApiExecutor.cs index 8bdf6bc1..b5d14805 100644 --- a/src/Crowdin.Api/Tasks/TasksApiExecutor.cs +++ b/src/Crowdin.Api/Tasks/TasksApiExecutor.cs @@ -1,4 +1,4 @@ - + using System.Collections.Generic; using System.Net; using System.Threading.Tasks; @@ -45,6 +45,23 @@ public Task> ListTasks( return ListTasks(projectId, new TasksListParams(limit, offset, status, assigneeId, orderBy)); } + /// + /// List tasks. Documentation: + /// Crowdin API + /// Crowdin Enterprise API + /// + [PublicAPI] + public Task> ListTasks( + int projectId, + int limit = 25, + int offset = 0, + IEnumerable? statuses = null, + int? assigneeId = null, + IEnumerable? orderBy = null) + { + return ListTasks(projectId, new TasksListParams(limit, offset, statuses, assigneeId, orderBy)); + } + /// /// List tasks. Documentation: /// Crowdin API diff --git a/src/Crowdin.Api/Tasks/TasksListParams.cs b/src/Crowdin.Api/Tasks/TasksListParams.cs index 3e31a056..c28fa842 100644 --- a/src/Crowdin.Api/Tasks/TasksListParams.cs +++ b/src/Crowdin.Api/Tasks/TasksListParams.cs @@ -1,5 +1,6 @@ - + using System.Collections.Generic; +using System.Linq; using Crowdin.Api.Core; using JetBrains.Annotations; @@ -13,9 +14,9 @@ public class TasksListParams : IQueryParamsProvider public int Limit { get; set; } = 25; public int Offset { get; set; } - - public TaskStatus? Status { get; set; } - + + public IEnumerable? Statuses { get; set; } + public int? AssigneeId { get; set; } public IEnumerable? OrderBy { get; set; } @@ -34,7 +35,21 @@ public TasksListParams( { Limit = limit; Offset = offset; - Status = status; + Statuses = status.HasValue ? new[] { status.Value } : null; + AssigneeId = assigneeId; + OrderBy = orderBy; + } + + public TasksListParams( + int limit, + int offset, + IEnumerable? statuses, + int? assigneeId, + IEnumerable? orderBy) + { + Limit = limit; + Offset = offset; + Statuses = statuses; AssigneeId = assigneeId; OrderBy = orderBy; } @@ -44,9 +59,9 @@ public IDictionary ToQueryParams() IDictionary queryParams = Utils.CreateQueryParamsFromPaging(Limit, Offset); - if (Status.HasValue) + if (Statuses != null && Statuses.Any()) { - queryParams.Add("status", Status.Value.ToDescriptionString()); + queryParams.Add("status", string.Join(",", Statuses.Select(status => status.ToDescriptionString()))); } queryParams.AddParamIfPresent("assigneeId", AssigneeId); diff --git a/tests/Crowdin.Api.UnitTesting/Resources/Tasks.Designer.cs b/tests/Crowdin.Api.UnitTesting/Resources/Tasks.Designer.cs index 43353133..d0be3bfa 100644 --- a/tests/Crowdin.Api.UnitTesting/Resources/Tasks.Designer.cs +++ b/tests/Crowdin.Api.UnitTesting/Resources/Tasks.Designer.cs @@ -1,4 +1,4 @@ -//------------------------------------------------------------------------------ +//------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:4.0.30319.42000 @@ -122,7 +122,17 @@ internal static string AddTask_RightRequestJson_VendorManual { return ResourceManager.GetString("AddTask_RightRequestJson_VendorManual", resourceCulture); } } - + + /// + /// + internal static string ListTasks + { + get + { + return ResourceManager.GetString("ListTasks", resourceCulture); + } + } + /// /// Looks up a localized string similar to { /// "precedingTaskId": 1, diff --git a/tests/Crowdin.Api.UnitTesting/Resources/Tasks.resx b/tests/Crowdin.Api.UnitTesting/Resources/Tasks.resx index 995616d3..e7618228 100644 --- a/tests/Crowdin.Api.UnitTesting/Resources/Tasks.resx +++ b/tests/Crowdin.Api.UnitTesting/Resources/Tasks.resx @@ -3,7 +3,7 @@ - + @@ -55,6 +55,125 @@ "wordsCount": 30 } ] +} + + + { + "data": [ + { + "data": { + "id": 2, + "projectId": 2, + "creatorId": 6, + "type": 1, + "status": "todo", + "title": "French", + "assignees": [ + { + "id": 12, + "username": "john_smith", + "fullName": "John Smith", + "avatarUrl": "", + "wordsCount": 5, + "wordsLeft": 3 + } + ], + "assignedTeams": [ + { + "id": 1, + "wordsCount": 5 + } + ], + "progress": { + "total": 24, + "done": 15, + "percent": 62 + }, + "translateProgress": { + "total": 24, + "done": 15, + "percent": 62 + }, + "sourceLanguageId": "en", + "targetLanguageId": "fr", + "description": "Proofread all French strings", + "translationUrl": "/proofread/9092638ac9f2a2d1b5571d08edc53763/all/en-fr/10?task=dac37aff364d83899128e68afe0de4994", + "webUrl": "https://crowdin.com/project/example-project/tasks/1", + "wordsCount": 24, + "commentsCount": 0, + "deadline": "2019-09-27T07:00:14+00:00", + "startedAt": "2019-09-27T07:00:14+00:00", + "resolvedAt": "2019-09-27T07:00:14+00:00", + "timeRange": "2019-08-23T09:04:29+00:00|2019-07-23T09:04:29+00:00", + "workflowStepId": 10, + "buyUrl": "https://www.paypal.com/cgi-bin/webscr?cmd=...", + "createdAt": "2019-09-23T09:04:29+00:00", + "updatedAt": "2019-09-23T09:04:29+00:00", + "sourceLanguage": { + "id": "es", + "name": "Spanish", + "editorCode": "es", + "twoLettersCode": "es", + "threeLettersCode": "spa", + "locale": "es-ES", + "androidCode": "es-rES", + "osxCode": "es.lproj", + "osxLocale": "es", + "pluralCategoryNames": [ + "one" + ], + "pluralRules": "(n != 1)", + "pluralExamples": [ + "0, 2-999; 1.2, 2.07..." + ], + "textDirection": "ltr", + "dialectOf": "es" + }, + "targetLanguages": [ + { + "id": "es", + "name": "Spanish", + "editorCode": "es", + "twoLettersCode": "es", + "threeLettersCode": "spa", + "locale": "es-ES", + "androidCode": "es-rES", + "osxCode": "es.lproj", + "osxLocale": "es", + "pluralCategoryNames": [ + "one" + ], + "pluralRules": "(n != 1)", + "pluralExamples": [ + "0, 2-999; 1.2, 2.07..." + ], + "textDirection": "ltr", + "dialectOf": "es" + } + ], + "labelIds": [ + 13, + 27 + ], + "excludeLabelIds": [ + 5, + 8 + ], + "precedingTaskId": 1, + "vendor": "gengo", + "filesCount": 3, + "fileIds": [ + 24, + 25, + 38 + ] + } + } + ], + "pagination": { + "offset": 0, + "limit": 25 + } } diff --git a/tests/Crowdin.Api.UnitTesting/Tests/Tasks/TasksApiTests.cs b/tests/Crowdin.Api.UnitTesting/Tests/Tasks/TasksApiTests.cs index 6d98632f..0e8c96a2 100644 --- a/tests/Crowdin.Api.UnitTesting/Tests/Tasks/TasksApiTests.cs +++ b/tests/Crowdin.Api.UnitTesting/Tests/Tasks/TasksApiTests.cs @@ -1,5 +1,11 @@ -using Crowdin.Api.Tasks; +using Crowdin.Api.Core; +using Crowdin.Api.Screenshots; +using Crowdin.Api.Tasks; +using Moq; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.Collections.Generic; +using System.Net; using Xunit; namespace Crowdin.Api.UnitTesting.Tests.Tasks @@ -76,5 +82,51 @@ public void AddTask_VendorManual_RequestSerialization() string expectedRequestJson = TestUtils.CompactJson(Resources.Tasks.AddTask_RightRequestJson_VendorManual); Assert.Equal(expectedRequestJson, actualRequestJson); } + + [Fact] + public async System.Threading.Tasks.Task ListTasks() + { + const int projectId = 1; + + var url = $"/projects/{projectId}/tasks"; + + var queryParams = new Dictionary + { + { "limit", "25" }, + { "offset", "0" }, + { "status", "todo,in_progress" }, + { "assigneeId", "1" }, + { "orderBy", "createdAt desc,name asc" }, + + }; + + Mock mockClient = TestUtils.CreateMockClientWithDefaultParser(); + + mockClient + .Setup(client => client.SendGetRequest(url, queryParams)) + .ReturnsAsync(new CrowdinApiResult + { + StatusCode = HttpStatusCode.OK, + JsonObject = JObject.Parse(Resources.Tasks.ListTasks) + }); + + var executor = new TasksApiExecutor(mockClient.Object); + var statuses = new TaskStatus[] { TaskStatus.Todo, TaskStatus.InProgress }; + var assigneeId = 1; + var sortingRules = new SortingRule[] { + new SortingRule() { Field = "createdAt", Order = SortingOrder.Descending }, + new SortingRule() { Field = "name", Order = SortingOrder.Ascending } + }; + + var response = await executor.ListTasks(projectId, 25, 0, statuses, assigneeId, sortingRules); + + Assert.NotNull(response); + + Assert.Equal(25, response.Pagination?.Limit); + Assert.Equal(0, response.Pagination?.Offset); + + Assert.Single(response.Data); + Assert.Equal(2, response.Data[0].Id); + } } } \ No newline at end of file