diff --git a/lib/asana_ex/client.ex b/lib/asana_ex/client.ex index 257febe..98371db 100644 --- a/lib/asana_ex/client.ex +++ b/lib/asana_ex/client.ex @@ -79,6 +79,69 @@ defmodule AsanaEx.Client do end end + @doc """ + Retrieve all projects by workspace gid + """ + @impl true + def all_workspace_projects( + _workspace_gis, + _assignee_gid, + _token, + _fields \\ "name,notes", + _limit \\ 100, + _offset \\ nil, + _projects \\ [] + ) + + def all_workspace_projects([], _assignee_gid, _token, _fields, _limit, _offset, projects), do: projects + + def all_workspace_projects(workspace_gids, assignee_gid, token, fields, limit, _offset, _projects) + when is_list(workspace_gids) do + Task.Supervisor.async_stream( + AsanaEx.HttpSupervisor, + workspace_gids, + __MODULE__, + :all_workspace_projects, + [assignee_gid, token, fields, limit], + timeout: 30_000 + ) + end + + def all_workspace_projects(workspace_gid, assignee_gid, token, fields, limit, offset, projects) do + params = + query_params_with_optional_offset( + [workspace: workspace_gid, assignee: assignee_gid, opt_fields: fields, limit: limit], + offset + ) + + path = "projects?" <> params + + {:ok, response} = http_impl().build(:get, token, path) + + next_page_offset = get_in(response, ["next_page", "offset"]) + + cond do + is_nil(response["data"]) -> + projects + + not is_nil(next_page_offset) -> + projects = projects ++ response["data"] + + all_workspace_tasks( + workspace_gid, + assignee_gid, + fields, + limit, + token, + next_page_offset, + projects + ) + + true -> + projects ++ response["data"] + end + end + @impl true def maybe_get_subtasks(_tasks, _assigneed_gid, _token, _fields \\ nil, _limit \\ 100) def maybe_get_subtasks([], _assigneed_gid, _token, _fields, _limit), do: [] diff --git a/test/asana_client_test.exs b/test/asana_client_test.exs index 7c56ce1..9d47c3f 100644 --- a/test/asana_client_test.exs +++ b/test/asana_client_test.exs @@ -54,6 +54,33 @@ defmodule AsanaEx.ClientTest do assert 15 == Enum.count(tasks) end + test "builds and sends Asana requests for projects" do + parent = self() + ref = make_ref() + + expect(MockHttp, :build, 1, fn :get, _token, _path -> + send(parent, {ref, :two}) + {:ok, fixture("project2.json")} + end) + + expect(MockHttp, :build, 1, fn :get, _token, _path -> + send(parent, {ref, :one}) + {:ok, fixture("project1.json")} + end) + + workspace_gids = ["12345", "67890"] + + projects = + AsanaEx.Client.all_workspace_projects(workspace_gids, "12345", "mytoken") + |> Enum.to_list() + |> Enum.flat_map(fn {_, items} -> items end) + + assert_receive {^ref, :one} + assert_receive {^ref, :two} + + assert 5 == Enum.count(projects) + end + test "recursively retrieves subtasks for a collection of tasks" do parent = self() ref = make_ref() diff --git a/test/fixtures/project1.json b/test/fixtures/project1.json new file mode 100644 index 0000000..961133d --- /dev/null +++ b/test/fixtures/project1.json @@ -0,0 +1,24 @@ + { + "data": [ + { + "gid": "2264755603111367", + "name": "Development Team Project", + "resource_type": "project" + }, + { + "gid": "2274755603111367", + "name": "Product Team Project", + "resource_type": "project" + }, + { + "gid": "2235774493276937", + "name": "Design Team Project", + "resource_type": "project" + } + ], + "next_page": { + "offset": "next-offset-for-project-1", + "path": "/projects?workspace=11111111111111&assignee=1111111111111111&limit=20&offset=next-offset-for-project-1", + "uri": "https://app.asana.com/api/1.0/projects?workspace=11111111111111&assignee=1111111111111111&limit=20&offset=next-offset-for-project-1" + } +} diff --git a/test/fixtures/project2.json b/test/fixtures/project2.json new file mode 100644 index 0000000..29d813b --- /dev/null +++ b/test/fixtures/project2.json @@ -0,0 +1,14 @@ + { + "data": [ + { + "gid": "3264755603111367", + "name": "Marketing Team Project", + "resource_type": "project" + }, + { + "gid": "3335774493276937", + "name": "Leadership Team Project", + "resource_type": "project" + } + ] +}