diff --git a/lib/code_corps_web/controllers/project_controller.ex b/lib/code_corps_web/controllers/project_controller.ex index a506effe9..5199f7fbe 100644 --- a/lib/code_corps_web/controllers/project_controller.ex +++ b/lib/code_corps_web/controllers/project_controller.ex @@ -45,9 +45,9 @@ defmodule CodeCorpsWeb.ProjectController do end @preloads [ - :donation_goals, [organization: :stripe_connect_account], - :project_categories, :project_github_repos, :project_skills, - :project_users, :stripe_connect_plan, :task_lists, :tasks + :donation_goals, [organization: [:organization_github_app_installations, :projects, :slugged_route, :stripe_connect_account]], + :project_categories, :project_github_repos, [project_skills: :skill], + [project_users: :user], :stripe_connect_plan, :task_lists, :tasks ] def preload(data) do diff --git a/lib/code_corps_web/controllers/project_skill_controller.ex b/lib/code_corps_web/controllers/project_skill_controller.ex index cd0d45bf8..d02cdfbdc 100644 --- a/lib/code_corps_web/controllers/project_skill_controller.ex +++ b/lib/code_corps_web/controllers/project_skill_controller.ex @@ -10,14 +10,14 @@ defmodule CodeCorpsWeb.ProjectSkillController do @spec index(Conn.t, map) :: Conn.t def index(%Conn{} = conn, %{} = params) do - with project_skills <- ProjectSkill |> Query.id_filter(params) |> Repo.all do + with project_skills <- ProjectSkill |> Query.id_filter(params) |> Repo.all |> preload() do conn |> render("index.json-api", data: project_skills) end end @spec show(Conn.t, map) :: Conn.t def show(%Conn{} = conn, %{"id" => id}) do - with %ProjectSkill{} = project_skill <- ProjectSkill |> Repo.get(id) do + with %ProjectSkill{} = project_skill <- ProjectSkill |> Repo.get(id) |> preload() do conn |> render("show.json-api", data: project_skill) end end @@ -26,8 +26,9 @@ defmodule CodeCorpsWeb.ProjectSkillController do def create(%Conn{} = conn, %{} = params) do with %User{} = current_user <- conn |> Guardian.Plug.current_resource, {:ok, :authorized} <- current_user |> Policy.authorize(:create, %ProjectSkill{}, params), - {:ok, %ProjectSkill{} = project_skill} <- %ProjectSkill{} |> ProjectSkill.create_changeset(params) |> Repo.insert do - + {:ok, %ProjectSkill{} = project_skill} <- %ProjectSkill{} |> ProjectSkill.create_changeset(params) |> Repo.insert(), + project_skill <- preload(project_skill) + do current_user.id |> SegmentTracker.track("Added Project Skill", project_skill) conn |> put_status(:created) |> render("show.json-api", data: project_skill) end @@ -44,4 +45,12 @@ defmodule CodeCorpsWeb.ProjectSkillController do conn |> Conn.assign(:project_skill, project_skill) |> send_resp(:no_content, "") end end + + @preloads [ + :skill + ] + + def preload(data) do + Repo.preload(data, @preloads) + end end diff --git a/lib/code_corps_web/controllers/task_controller.ex b/lib/code_corps_web/controllers/task_controller.ex index e5954bbb2..d7f2712cc 100644 --- a/lib/code_corps_web/controllers/task_controller.ex +++ b/lib/code_corps_web/controllers/task_controller.ex @@ -62,7 +62,7 @@ defmodule CodeCorpsWeb.TaskController do end end - @preloads [:comments, :github_pull_request, :task_skills, :user_task] + @preloads [:comments, :github_pull_request, :task_skills, :user, [user_task: :user]] def preload(data) do timing("TaskController", "preload") do diff --git a/lib/code_corps_web/controllers/task_list_controller.ex b/lib/code_corps_web/controllers/task_list_controller.ex index 6fa9682b9..836418500 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_issue, :github_pull_request, :task_skills, :user, [user_task: :user]]] def preload(data) do Repo.preload(data, @preloads) diff --git a/lib/code_corps_web/views/project_skill_view.ex b/lib/code_corps_web/views/project_skill_view.ex index 5621d929b..2db46b2fb 100644 --- a/lib/code_corps_web/views/project_skill_view.ex +++ b/lib/code_corps_web/views/project_skill_view.ex @@ -4,5 +4,5 @@ defmodule CodeCorpsWeb.ProjectSkillView do use JaSerializer.PhoenixView has_one :project, type: "project", field: :project_id - has_one :skill, type: "skill", field: :skill_id + has_one :skill, serializer: CodeCorpsWeb.SkillView, include: true end diff --git a/lib/code_corps_web/views/project_user_view.ex b/lib/code_corps_web/views/project_user_view.ex index 6b5bd0f26..a36d713d7 100644 --- a/lib/code_corps_web/views/project_user_view.ex +++ b/lib/code_corps_web/views/project_user_view.ex @@ -6,5 +6,5 @@ defmodule CodeCorpsWeb.ProjectUserView do attributes [:role, :inserted_at, :updated_at] has_one :project, type: "project", field: :project_id - has_one :user, type: "user", field: :user_id + has_one :user, serializer: CodeCorpsWeb.UserSlimView, include: true end diff --git a/lib/code_corps_web/views/skill_view.ex b/lib/code_corps_web/views/skill_view.ex index 2ce0ebb2c..47b1e38c1 100644 --- a/lib/code_corps_web/views/skill_view.ex +++ b/lib/code_corps_web/views/skill_view.ex @@ -4,6 +4,4 @@ defmodule CodeCorpsWeb.SkillView do use JaSerializer.PhoenixView attributes [:title, :description, :inserted_at, :updated_at] - - has_many :role_skills, serializer: CodeCorpsWeb.RoleSkillView, identifiers: :always end diff --git a/lib/code_corps_web/views/task_in_list_view.ex b/lib/code_corps_web/views/task_in_list_view.ex new file mode 100644 index 000000000..5b5f5a293 --- /dev/null +++ b/lib/code_corps_web/views/task_in_list_view.ex @@ -0,0 +1,21 @@ +defmodule CodeCorpsWeb.TaskInListView do + @moduledoc false + use CodeCorpsWeb, :view + use JaSerializer.PhoenixView + + def type, do: "task" + + attributes [ + :archived, :created_at, :number, :order, :status, :title + ] + + has_one :github_issue, serializer: CodeCorpsWeb.GithubIssueView, 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 :project, type: "project", field: :project_id + has_one :task_list, type: "task-list", field: :task_list_id + has_one :user, serializer: CodeCorpsWeb.UserSlimView, include: true + has_one :user_task, serializer: CodeCorpsWeb.UserTaskView, include: true + + has_many :task_skills, serializer: CodeCorpsWeb.TaskSkillView, include: true +end diff --git a/lib/code_corps_web/views/task_view.ex b/lib/code_corps_web/views/task_view.ex index 9a2a9f517..d747c987d 100644 --- a/lib/code_corps_web/views/task_view.ex +++ b/lib/code_corps_web/views/task_view.ex @@ -13,8 +13,8 @@ defmodule CodeCorpsWeb.TaskView do has_one :github_repo, type: "github-repo", field: :github_repo_id has_one :project, type: "project", field: :project_id has_one :task_list, type: "task-list", field: :task_list_id - has_one :user, type: "user", field: :user_id - has_one :user_task, serializer: CodeCorpsWeb.UserTaskView, identifiers: :always + has_one :user, serializer: CodeCorpsWeb.UserSlimView, include: true + has_one :user_task, serializer: CodeCorpsWeb.UserTaskView, include: true has_many :comments, serializer: CodeCorpsWeb.CommentView, identifiers: :always has_many :task_skills, serializer: CodeCorpsWeb.TaskSkillView, identifiers: :always diff --git a/lib/code_corps_web/views/user_slim_view.ex b/lib/code_corps_web/views/user_slim_view.ex new file mode 100644 index 000000000..ec8c72de9 --- /dev/null +++ b/lib/code_corps_web/views/user_slim_view.ex @@ -0,0 +1,57 @@ +defmodule CodeCorpsWeb.UserSlimView do + @moduledoc false + alias CodeCorps.Presenters.ImagePresenter + + use CodeCorpsWeb, :view + use JaSerializer.PhoenixView + + def type, do: "user" + + attributes [ + :biography, :cloudinary_public_id, :email, :first_name, + :github_avatar_url, :github_id, :github_username, :intercom_user_hash, + :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: "" + + @intercom_secret_key Application.get_env(:code_corps, :intercom_identity_secret_key) || "RANDOM_KEY" + + def intercom_user_hash(%{id: id}, _conn) when is_number(id) do + id |> Integer.to_string |> do_intercom_user_hash + end + # def intercom_user_hash(_user, _conn), do: nil + + defp do_intercom_user_hash(id_string) do + :crypto.hmac(:sha256, @intercom_secret_key, id_string) + |> Base.encode16 + |> String.downcase + end + + @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 diff --git a/lib/code_corps_web/views/user_task_view.ex b/lib/code_corps_web/views/user_task_view.ex index 80b87723c..30ad5d7f8 100644 --- a/lib/code_corps_web/views/user_task_view.ex +++ b/lib/code_corps_web/views/user_task_view.ex @@ -4,5 +4,5 @@ defmodule CodeCorpsWeb.UserTaskView do use JaSerializer.PhoenixView has_one :task, type: "task", field: :task_id - has_one :user, type: "user", field: :user_id + has_one :user, serializer: CodeCorpsWeb.UserSlimView, include: true end