Skip to content

Commit

Permalink
feat(tasks): Allow querying tasks by multiple statuses
Browse files Browse the repository at this point in the history
  • Loading branch information
a.mikava committed Jan 16, 2025
1 parent 71bca8d commit 921edf7
Show file tree
Hide file tree
Showing 6 changed files with 233 additions and 12 deletions.
8 changes: 8 additions & 0 deletions src/Crowdin.Api/Tasks/ITasksApiExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ Task<ResponseList<TaskResource>> ListTasks(
int? assigneeId = null,
IEnumerable<SortingRule>? orderBy = null);

Task<ResponseList<TaskResource>> ListTasks(
int projectId,
int limit = 25,
int offset = 0,
IEnumerable<TaskStatus>? statuses = null,
int? assigneeId = null,
IEnumerable<SortingRule>? orderBy = null);

Task<ResponseList<TaskResource>> ListTasks(int projectId, TasksListParams @params);

Task<TaskResource> AddTask(int projectId, AddTaskRequest request);
Expand Down
19 changes: 18 additions & 1 deletion src/Crowdin.Api/Tasks/TasksApiExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@


using System.Collections.Generic;
using System.Net;
using System.Threading.Tasks;
Expand Down Expand Up @@ -45,6 +45,23 @@ public Task<ResponseList<TaskResource>> ListTasks(
return ListTasks(projectId, new TasksListParams(limit, offset, status, assigneeId, orderBy));
}

/// <summary>
/// List tasks. Documentation:
/// <a href="https://support.crowdin.com/api/v2/#operation/api.projects.tasks.getMany">Crowdin API</a>
/// <a href="https://support.crowdin.com/enterprise/api/#operation/api.projects.tasks.getMany">Crowdin Enterprise API</a>
/// </summary>
[PublicAPI]
public Task<ResponseList<TaskResource>> ListTasks(
int projectId,
int limit = 25,
int offset = 0,
IEnumerable<TaskStatus>? statuses = null,
int? assigneeId = null,
IEnumerable<SortingRule>? orderBy = null)
{
return ListTasks(projectId, new TasksListParams(limit, offset, statuses, assigneeId, orderBy));
}

/// <summary>
/// List tasks. Documentation:
/// <a href="https://support.crowdin.com/api/v2/#operation/api.projects.tasks.getMany">Crowdin API</a>
Expand Down
29 changes: 22 additions & 7 deletions src/Crowdin.Api/Tasks/TasksListParams.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@


using System.Collections.Generic;
using System.Linq;
using Crowdin.Api.Core;
using JetBrains.Annotations;

Expand All @@ -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<TaskStatus>? Statuses { get; set; }

public int? AssigneeId { get; set; }

public IEnumerable<SortingRule>? OrderBy { get; set; }
Expand All @@ -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<TaskStatus>? statuses,
int? assigneeId,
IEnumerable<SortingRule>? orderBy)
{
Limit = limit;
Offset = offset;
Statuses = statuses;
AssigneeId = assigneeId;
OrderBy = orderBy;
}
Expand All @@ -44,9 +59,9 @@ public IDictionary<string, string> ToQueryParams()
IDictionary<string, string> 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);
Expand Down
14 changes: 12 additions & 2 deletions tests/Crowdin.Api.UnitTesting/Resources/Tasks.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

121 changes: 120 additions & 1 deletion tests/Crowdin.Api.UnitTesting/Resources/Tasks.resx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">

</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
Expand Down Expand Up @@ -55,6 +55,125 @@
"wordsCount": 30
}
]
}</value>
</data>
<data name="ListTasks" xml:space="preserve">
<value>{
"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
}
}</value>
</data>
<data name="Request_PendingTaskCreateForm" xml:space="preserve">
Expand Down
54 changes: 53 additions & 1 deletion tests/Crowdin.Api.UnitTesting/Tests/Tasks/TasksApiTests.cs
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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<string, string>
{
{ "limit", "25" },
{ "offset", "0" },
{ "status", "todo,in_progress" },
{ "assigneeId", "1" },
{ "orderBy", "createdAt desc,name asc" },

};

Mock<ICrowdinApiClient> 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);
}
}
}

0 comments on commit 921edf7

Please sign in to comment.