diff --git a/lib/code_corps_web/controllers/task_list_controller.ex b/lib/code_corps_web/controllers/task_list_controller.ex index 6fa9682b9..0b30a50cc 100644 --- a/lib/code_corps_web/controllers/task_list_controller.ex +++ b/lib/code_corps_web/controllers/task_list_controller.ex @@ -28,7 +28,7 @@ defmodule CodeCorpsWeb.TaskListController do end end - @preloads [:tasks] + @preloads [tasks: [:github_pull_request, :github_issue, :github_repo, :user_task, :user]] def preload(data) do Repo.preload(data, @preloads) diff --git a/lib/code_corps_web/views/task_list_view.ex b/lib/code_corps_web/views/task_list_view.ex index a6ccad2e4..79b855a7d 100644 --- a/lib/code_corps_web/views/task_list_view.ex +++ b/lib/code_corps_web/views/task_list_view.ex @@ -7,5 +7,5 @@ defmodule CodeCorpsWeb.TaskListView do has_one :project, type: "project", field: :project_id - has_many :tasks, serializer: CodeCorpsWeb.TaskView, identifiers: :always + has_many :tasks, serializer: CodeCorpsWeb.TaskIncludedView, identifiers: :always, include: true end diff --git a/lib/code_corps_web/views/task_view.ex b/lib/code_corps_web/views/task_view.ex index 9f0ee1c9e..c3a7d9389 100644 --- a/lib/code_corps_web/views/task_view.ex +++ b/lib/code_corps_web/views/task_view.ex @@ -37,3 +37,27 @@ defmodule CodeCorpsWeb.TaskView do status end end + +defmodule CodeCorpsWeb.TaskIncludedView do + @moduledoc false + use CodeCorpsWeb, :view + use JaSerializer.PhoenixView + + def type, do: "task" + + attributes [ + :archived, :body, :created_at, :created_from, :has_github_pull_request, :inserted_at, + :markdown, :modified_at, :modified_from, :number, :order, :status, :title, :updated_at + ] + + has_one :github_issue, type: "github-issue", field: :github_issue_id, include: true + has_one :github_pull_request, serializer: CodeCorpsWeb.GithubPullRequestView, include: true + has_one :github_repo, type: "github-repo", field: :github_repo_id + has_one :user, serializer: CodeCorpsWeb.UserIncludedView, include: true + has_one :user_task, serializer: CodeCorpsWeb.UserTaskView, include: true + + def has_github_pull_request(%{ + github_pull_request: %CodeCorps.GithubPullRequest{} + }), do: true + def has_github_pull_request(%{github_pull_request: nil}), do: false +end diff --git a/lib/code_corps_web/views/user_view.ex b/lib/code_corps_web/views/user_view.ex index fb01112dd..c81ecf80f 100644 --- a/lib/code_corps_web/views/user_view.ex +++ b/lib/code_corps_web/views/user_view.ex @@ -66,3 +66,48 @@ defmodule CodeCorpsWeb.UserView do defp normalize_name(name) when name in ["", nil], do: nil defp normalize_name(name), do: name end + +defmodule CodeCorpsWeb.UserIncludedView do + @moduledoc false + alias CodeCorps.Presenters.ImagePresenter + + use CodeCorpsWeb, :view + use JaSerializer.PhoenixView + + def type, do: "user" + + attributes [ + :admin, :biography, :cloudinary_public_id, :email, :first_name, + :github_avatar_url, :github_id, :github_username, + :inserted_at, :last_name, :name, :photo_large_url, :photo_thumb_url, + :sign_up_context, :state, :state_transition, :twitter, :username, + :website, :updated_at + ] + + def photo_large_url(user, _conn), do: ImagePresenter.large(user) + + def photo_thumb_url(user, _conn), do: ImagePresenter.thumbnail(user) + + @doc """ + Returns the user email or an empty string, depending on the user + being rendered is the authenticated user, or some other user. + + Users can only see their own emails. Everyone else's are private. + """ + def email(user, %Plug.Conn{assigns: %{current_user: current_user}}) do + if user.id == current_user.id, do: user.email, else: "" + end + def email(_user, _conn), do: "" + + @doc """ + Returns the user's full name when both first and last name are present. + Returns the only user's first name or last name when the other is missing, + otherwise returns nil. + """ + def name(%{first_name: first_name, last_name: last_name}, _conn) do + "#{first_name} #{last_name}" |> String.trim |> normalize_name + end + + defp normalize_name(name) when name in ["", nil], do: nil + defp normalize_name(name), do: name +end \ No newline at end of file diff --git a/priv/repo/structure.sql b/priv/repo/structure.sql index 9691dab1f..d18b9d7a1 100644 --- a/priv/repo/structure.sql +++ b/priv/repo/structure.sql @@ -2,8 +2,8 @@ -- PostgreSQL database dump -- --- Dumped from database version 9.5.10 --- Dumped by pg_dump version 10.1 +-- Dumped from database version 9.6.6 +-- Dumped by pg_dump version 9.6.6 SET statement_timeout = 0; SET lock_timeout = 0; diff --git a/test/lib/code_corps_web/views/task_list_view_test.exs b/test/lib/code_corps_web/views/task_list_view_test.exs index a0332d8f3..d7fb8fec0 100644 --- a/test/lib/code_corps_web/views/task_list_view_test.exs +++ b/test/lib/code_corps_web/views/task_list_view_test.exs @@ -2,9 +2,11 @@ defmodule CodeCorpsWeb.TaskListViewTest do use CodeCorpsWeb.ViewCase test "renders all attributes and relationships properly" do + user = insert(:user, first_name: "First", last_name: "Last", default_color: "blue") + host = Application.get_env(:code_corps, :asset_host) project = insert(:project) task_list = insert(:task_list, order: 1000, project: project) - task = insert(:task, order: 1000, task_list: task_list) + task = insert(:task, order: 1000, task_list: task_list, user: user) task_list = CodeCorpsWeb.TaskListController.preload(task_list) rendered_json = render(CodeCorpsWeb.TaskListView, "show.json-api", data: task_list) @@ -39,7 +41,73 @@ defmodule CodeCorpsWeb.TaskListViewTest do }, "jsonapi" => %{ "version" => "1.0" - } + }, + "included" => [%{ + "attributes" => %{ + "archived" => task.archived, + "body" => task.body, + "created-at" => task.created_at, + "created-from" => task.created_from, + "has-github-pull-request" => false, + "inserted-at" => task.inserted_at, + "markdown" => task.markdown, + "modified-at" => task.modified_at, + "modified-from" => task.modified_from, + "number" => task.number, + "order" => task.order, + "status" => task.status, + "title" => task.title, + "updated-at" => task.updated_at + }, + "relationships" => %{ + "github-issue" => %{ + "data" => nil + }, + "github-repo" => %{ + "data" => nil + }, + "user-task" => %{ + "data" => nil + }, + "user" => %{ + "data" => %{ + "id" => task.user.id |> Integer.to_string, + "type" => "user" + } + }, + "github-pull-request" => %{ + "data" => nil + }, + }, + "id" => task.id |> Integer.to_string, + "type" => "task" + }, + %{ + "attributes" => %{ + "admin" => false, + "biography" => user.biography, + "cloudinary-public-id" => nil, + "email" => "", + "first-name" => user.first_name, + "github-avatar-url" => nil, + "github-id" => nil, + "github-username" => nil, + "inserted-at" => user.inserted_at, + "last-name" => user.last_name, + "name" => "First Last", + "photo-large-url" => "#{host}/icons/user_default_large_blue.png", + "photo-thumb-url" => "#{host}/icons/user_default_thumb_blue.png", + "sign-up-context" => "default", + "state" => "signed_up", + "state-transition" => nil, + "twitter" => user.twitter, + "username" => user.username, + "updated-at" => user.updated_at, + "website" => user.website + }, + "id" => user.id |> Integer.to_string, + "type" => "user" + }] } assert rendered_json == expected_json