diff --git a/lib/mindwendel/brainstormings.ex b/lib/mindwendel/brainstormings.ex index 80567d80..4c06a94d 100644 --- a/lib/mindwendel/brainstormings.ex +++ b/lib/mindwendel/brainstormings.ex @@ -9,10 +9,8 @@ defmodule Mindwendel.Brainstormings do alias Mindwendel.Brainstormings.Idea alias Mindwendel.Accounts.User alias Mindwendel.Brainstormings.IdeaLabel - alias Mindwendel.Brainstormings.IdeaIdeaLabel alias Mindwendel.Brainstormings.Brainstorming alias Mindwendel.Brainstormings.BrainstormingModeratingUser - alias Mindwendel.Brainstormings.Like require Logger @@ -41,220 +39,6 @@ defmodule Mindwendel.Brainstormings do |> Repo.insert() end - @doc """ - Returns the list of ideas. - - ## Examples - - iex> list_ideas() - [%Idea{}, ...] - - """ - def list_ideas do - Repo.all(Idea) - end - - @doc """ - Returns the list of ideas depending on the brainstorming id. - - ## Examples - - iex> list_ideas(3) - [%Idea{}, ...] - - """ - def list_ideas_for_brainstorming(id) do - idea_count_query = - from like in Like, - group_by: like.idea_id, - select: %{idea_id: like.idea_id, like_count: count(1)} - - idea_query = - from idea in Idea, - left_join: idea_count in subquery(idea_count_query), - on: idea_count.idea_id == idea.id, - where: idea.brainstorming_id == ^id, - order_by: [desc_nulls_last: idea_count.like_count, desc: idea.inserted_at] - - Repo.all(idea_query) - |> Repo.preload([ - :link, - :likes, - :label, - :idea_labels - ]) - end - - def sort_ideas_by_labels(brainstorming_id) do - from( - idea in Idea, - left_join: l in assoc(idea, :idea_labels), - where: idea.brainstorming_id == ^brainstorming_id, - preload: [ - :link, - :likes, - :idea_labels - ], - order_by: [ - asc_nulls_last: l.position_order, - desc: idea.inserted_at - ] - ) - |> Repo.all() - |> Enum.uniq() - end - - @doc """ - Gets a single idea. - - Raises `Ecto.NoResultsError` if the Idea does not exist. - - ## Examples - - iex> get_idea!(123) - %Idea{} - - iex> get_idea!(456) - ** (Ecto.NoResultsError) - - """ - def get_idea!(id), do: Repo.get!(Idea, id) |> Repo.preload([:label, :idea_labels]) - - @doc """ - Count likes for an idea. - - ## Examples - - iex> count_likes_for_idea(idea) - 5 - - """ - def count_likes_for_idea(idea), do: idea |> Ecto.assoc(:likes) |> Repo.aggregate(:count, :id) - - @doc """ - Creates a idea. - - ## Examples - - iex> create_idea(%{field: value}) - {:ok, %Idea{}} - - iex> create_idea(%{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def create_idea(attrs \\ %{}) do - %Idea{} - |> Idea.changeset(attrs) - |> Repo.insert() - |> case do - {:ok, result} -> scan_for_link_in_idea(result) - {_, result} -> {:error, result} - end - |> broadcast(:idea_added) - end - - @doc """ - Scans for links in the idea body and adds a link entity if present. - - ## Examples - - iex> scan_for_link_in_idea(idea) - {:ok, idea} - - """ - def scan_for_link_in_idea(idea) do - Task.start(fn -> - Repo.preload(idea, :link) - |> Idea.build_link() - |> Repo.update() - |> broadcast(:idea_updated) - end) - - {:ok, idea} - end - - @doc """ - Updates a idea. - - ## Examples - - iex> update_idea(idea, %{field: new_value}) - {:ok, %Idea{}} - - iex> update_idea(idea, %{field: bad_value}) - {:error, %Ecto.Changeset{}} - - """ - def update_idea(%Idea{} = idea, attrs) do - idea - |> Idea.changeset(attrs) - |> Repo.update() - |> broadcast(:idea_updated) - end - - def update_idea_label(%Idea{} = idea, label) do - idea - |> Idea.changeset_update_label(label) - |> Repo.update() - |> broadcast(:idea_updated) - end - - def add_idea_label_to_idea(%Idea{} = idea, %IdeaLabel{} = idea_label) do - idea = Repo.preload(idea, :idea_labels) - - idea_labels = - (idea.idea_labels ++ [idea_label]) - |> Enum.map(&Ecto.Changeset.change/1) - - idea - |> Ecto.Changeset.change() - |> Ecto.Changeset.put_assoc(:idea_labels, idea_labels) - |> Repo.update() - |> broadcast(:idea_updated) - end - - def remove_idea_label_from_idea(%Idea{} = idea, %IdeaLabel{} = idea_label) do - from(idea_idea_label in IdeaIdeaLabel, - where: - idea_idea_label.idea_id == ^idea.id and - idea_idea_label.idea_label_id == ^idea_label.id - ) - |> Repo.delete_all() - - {:ok, get_idea!(idea.id)} |> broadcast(:idea_updated) - end - - @doc """ - Deletes a idea. - - ## Examples - - iex> delete_idea(idea) - {:ok, %Idea{}} - - iex> delete_idea(idea) - {:error, %Ecto.Changeset{}} - - """ - def delete_idea(%Idea{} = idea) do - Repo.delete(idea) - broadcast({:ok, idea}, :idea_removed) - end - - @doc """ - Returns an `%Ecto.Changeset{}` for tracking idea changes. - - ## Examples - - iex> change_idea(idea) - %Ecto.Changeset{data: %Idea{}} - - """ - def change_idea(%Idea{} = idea, attrs \\ %{}) do - Repo.preload(idea, [:link, :idea_labels]) |> Idea.changeset(attrs) - end - @doc """ Returns the list of brainstormings. @@ -308,20 +92,6 @@ defmodule Mindwendel.Brainstormings do Repo.get_by!(Brainstorming, admin_url_id: admin_url_id) end - def get_idea_label!(id) do - Repo.get!(IdeaLabel, id) - end - - def get_idea_label(id) when not is_nil(id) do - Repo.get(IdeaLabel, id) - rescue - Ecto.Query.CastError -> nil - end - - def get_idea_label(id) when is_nil(id) do - nil - end - @doc """ Creates a brainstorming and associates a user as creating_user, moderatoring user (also called brainstorming admin) and user. @@ -330,7 +100,7 @@ defmodule Mindwendel.Brainstormings do ## Examples current_user = - MindwendelService.SessionService.get_current_user_id(conn) + Mindwendel.Services.SessionService.get_current_user_id(conn) |> Accounts.get_or_create_user() {:ok, %Brainstorming{ ... }} = @@ -442,58 +212,6 @@ defmodule Mindwendel.Brainstormings do Brainstorming.changeset(brainstorming, attrs) end - @doc """ - Returns a Boolean if a like for the given idea and user exists. - - ## Examples - - iex> exists_like_for_idea?(1, 2) - true - - """ - def exists_like_for_idea?(idea_id, user_id) do - Repo.exists?(from like in Like, where: like.user_id == ^user_id and like.idea_id == ^idea_id) - end - - @doc """ - Returns a broadcast tuple of the idea update. - - ## Examples - - iex> add_like(1, 2) - {:ok, %Idea{}} - - """ - def add_like(idea_id, user_id) do - {status, result} = - %Like{} - |> Like.changeset(%{idea_id: idea_id, user_id: user_id}) - |> Repo.insert() - - case status do - :ok -> {:ok, get_idea!(idea_id)} |> broadcast(:idea_updated) - :error -> {:error, result} - end - end - - @doc """ - Deletes a like for an idea by a given user - - ## Examples - - iex> delete_like(1, 2) - {:ok, %Idea{}} - - """ - def delete_like(idea_id, user_id) do - # we ignore the result, delete_all returns the count of deleted items. We'll reload and broadcast the idea either way: - Repo.delete_all( - from like in Like, where: like.user_id == ^user_id and like.idea_id == ^idea_id - ) - - {:ok, get_idea!(idea_id)} |> broadcast(:idea_updated) - end - @doc """ Returns a subscibe result. diff --git a/lib/mindwendel/csv_formatter.ex b/lib/mindwendel/csv_formatter.ex index fda8cbc9..97342fd4 100644 --- a/lib/mindwendel/csv_formatter.ex +++ b/lib/mindwendel/csv_formatter.ex @@ -1,5 +1,5 @@ defmodule Mindwendel.CSVFormatter do - alias Mindwendel.Brainstormings + alias Mindwendel.Likes def ideas_to_csv(ideas) do [["idea", "username", "likes"]] @@ -9,7 +9,7 @@ defmodule Mindwendel.CSVFormatter do &[ &1.body, Gettext.gettext(MindwendelWeb.Gettext, &1.username), - Brainstormings.count_likes_for_idea(&1) + Likes.count_likes_for_idea(&1) ] ) ) diff --git a/lib/mindwendel/idea_labels.ex b/lib/mindwendel/idea_labels.ex new file mode 100644 index 00000000..acd16fd2 --- /dev/null +++ b/lib/mindwendel/idea_labels.ex @@ -0,0 +1,51 @@ +defmodule Mindwendel.IdeaLabels do + @moduledoc """ + The Brainstormings context. + """ + + import Ecto.Query, warn: false + alias Mindwendel.Repo + + alias Mindwendel.Brainstormings.Idea + alias Mindwendel.Brainstormings + alias Mindwendel.Ideas + alias Mindwendel.Brainstormings.IdeaLabel + alias Mindwendel.Brainstormings.IdeaIdeaLabel + + require Logger + + def get_idea_label(id) when not is_nil(id) do + Repo.get(IdeaLabel, id) + rescue + Ecto.Query.CastError -> nil + end + + def get_idea_label(id) when is_nil(id) do + nil + end + + def add_idea_label_to_idea(%Idea{} = idea, %IdeaLabel{} = idea_label) do + idea = Repo.preload(idea, :idea_labels) + + idea_labels = + (idea.idea_labels ++ [idea_label]) + |> Enum.map(&Ecto.Changeset.change/1) + + idea + |> Ecto.Changeset.change() + |> Ecto.Changeset.put_assoc(:idea_labels, idea_labels) + |> Repo.update() + |> Brainstormings.broadcast(:idea_updated) + end + + def remove_idea_label_from_idea(%Idea{} = idea, %IdeaLabel{} = idea_label) do + from(idea_idea_label in IdeaIdeaLabel, + where: + idea_idea_label.idea_id == ^idea.id and + idea_idea_label.idea_label_id == ^idea_label.id + ) + |> Repo.delete_all() + + {:ok, Ideas.get_idea!(idea.id)} |> Brainstormings.broadcast(:idea_updated) + end +end diff --git a/lib/mindwendel/ideas.ex b/lib/mindwendel/ideas.ex new file mode 100644 index 00000000..353de5f2 --- /dev/null +++ b/lib/mindwendel/ideas.ex @@ -0,0 +1,185 @@ +defmodule Mindwendel.Ideas do + @moduledoc """ + The Brainstormings context. + """ + + import Ecto.Query, warn: false + alias Mindwendel.Repo + + alias Mindwendel.Brainstormings + alias Mindwendel.Brainstormings.Like + alias Mindwendel.Brainstormings.Idea + + require Logger + + @doc """ + Returns the list of ideas. + + ## Examples + + iex> list_ideas() + [%Idea{}, ...] + + """ + def list_ideas do + Repo.all(Idea) + end + + @doc """ + Returns the list of ideas depending on the brainstorming id. + + ## Examples + + iex> list_ideas(3) + [%Idea{}, ...] + + """ + def list_ideas_for_brainstorming(id) do + idea_count_query = + from like in Like, + group_by: like.idea_id, + select: %{idea_id: like.idea_id, like_count: count(1)} + + idea_query = + from idea in Idea, + left_join: idea_count in subquery(idea_count_query), + on: idea_count.idea_id == idea.id, + where: idea.brainstorming_id == ^id, + order_by: [desc_nulls_last: idea_count.like_count, desc: idea.inserted_at] + + Repo.all(idea_query) + |> Repo.preload([ + :link, + :likes, + :label, + :idea_labels + ]) + end + + def sort_ideas_by_labels(brainstorming_id) do + from( + idea in Idea, + left_join: l in assoc(idea, :idea_labels), + where: idea.brainstorming_id == ^brainstorming_id, + preload: [ + :link, + :likes, + :idea_labels + ], + order_by: [ + asc_nulls_last: l.position_order, + desc: idea.inserted_at + ] + ) + |> Repo.all() + |> Enum.uniq() + end + + @doc """ + Gets a single idea. + + Raises `Ecto.NoResultsError` if the Idea does not exist. + + ## Examples + + iex> get_idea!(123) + %Idea{} + + iex> get_idea!(456) + ** (Ecto.NoResultsError) + + """ + def get_idea!(id), do: Repo.get!(Idea, id) |> Repo.preload([:label, :idea_labels]) + + @doc """ + Creates a idea. + + ## Examples + + iex> create_idea(%{field: value}) + {:ok, %Idea{}} + + iex> create_idea(%{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def create_idea(attrs \\ %{}) do + %Idea{} + |> Idea.changeset(attrs) + |> Repo.insert() + |> case do + {:ok, result} -> scan_for_link_in_idea(result) + {_, result} -> {:error, result} + end + |> Brainstormings.broadcast(:idea_added) + end + + @doc """ + Scans for links in the idea body and adds a link entity if present. + + ## Examples + + iex> scan_for_link_in_idea(idea) + {:ok, idea} + + """ + def scan_for_link_in_idea(idea) do + Task.start(fn -> + Repo.preload(idea, :link) + |> Idea.build_link() + |> Repo.update() + |> Brainstormings.broadcast(:idea_updated) + end) + + {:ok, idea} + end + + @doc """ + Updates a idea. + + ## Examples + + iex> update_idea(idea, %{field: new_value}) + {:ok, %Idea{}} + + iex> update_idea(idea, %{field: bad_value}) + {:error, %Ecto.Changeset{}} + + """ + def update_idea(%Idea{} = idea, attrs) do + idea + |> Idea.changeset(attrs) + |> Repo.update() + |> Brainstormings.broadcast(:idea_updated) + end + + @doc """ + Deletes a idea. + + ## Examples + + iex> delete_idea(idea) + {:ok, %Idea{}} + + iex> delete_idea(idea) + {:error, %Ecto.Changeset{}} + + """ + def delete_idea(%Idea{} = idea) do + Repo.delete(idea) + Brainstormings.broadcast({:ok, idea}, :idea_removed) + end + + @doc """ + Returns an `%Ecto.Changeset{}` for tracking idea changes. + + ## Examples + + iex> change_idea(idea) + %Ecto.Changeset{data: %Idea{}} + + """ + def change_idea(%Idea{} = idea, attrs \\ %{}) do + Repo.preload(idea, [:link, :idea_labels]) |> Idea.changeset(attrs) + end +end diff --git a/lib/mindwendel/likes.ex b/lib/mindwendel/likes.ex new file mode 100644 index 00000000..b29baf09 --- /dev/null +++ b/lib/mindwendel/likes.ex @@ -0,0 +1,77 @@ +defmodule Mindwendel.Likes do + @moduledoc """ + The Brainstormings context. + """ + + import Ecto.Query, warn: false + alias Mindwendel.Repo + + alias Mindwendel.Brainstormings + alias Mindwendel.Ideas + alias Mindwendel.Brainstormings.Like + + require Logger + + @doc """ + Returns a Boolean if a like for the given idea and user exists. + + ## Examples + + iex> exists_like_for_idea?(1, 2) + true + + """ + def exists_like_for_idea?(idea_id, user_id) do + Repo.exists?(from like in Like, where: like.user_id == ^user_id and like.idea_id == ^idea_id) + end + + @doc """ + Returns a broadcast tuple of the idea update. + + ## Examples + + iex> add_like(1, 2) + {:ok, %Idea{}} + + """ + def add_like(idea_id, user_id) do + {status, result} = + %Like{} + |> Like.changeset(%{idea_id: idea_id, user_id: user_id}) + |> Repo.insert() + + case status do + :ok -> {:ok, Ideas.get_idea!(idea_id)} |> Brainstormings.broadcast(:idea_updated) + :error -> {:error, result} + end + end + + @doc """ + Deletes a like for an idea by a given user + + ## Examples + + iex> delete_like(1, 2) + {:ok, %Idea{}} + + """ + def delete_like(idea_id, user_id) do + # we ignore the result, delete_all returns the count of deleted items. We'll reload and broadcast the idea either way: + Repo.delete_all( + from like in Like, where: like.user_id == ^user_id and like.idea_id == ^idea_id + ) + + {:ok, Ideas.get_idea!(idea_id)} |> Brainstormings.broadcast(:idea_updated) + end + + @doc """ + Count likes for an idea. + + ## Examples + + iex> count_likes_for_idea(idea) + 5 + + """ + def count_likes_for_idea(idea), do: idea |> Ecto.assoc(:likes) |> Repo.aggregate(:count, :id) +end diff --git a/lib/mindwendel_service/session_service.ex b/lib/mindwendel/services/session_service.ex similarity index 91% rename from lib/mindwendel_service/session_service.ex rename to lib/mindwendel/services/session_service.ex index d9f1f7fc..e6f49fa0 100644 --- a/lib/mindwendel_service/session_service.ex +++ b/lib/mindwendel/services/session_service.ex @@ -1,4 +1,4 @@ -defmodule MindwendelService.SessionService do +defmodule Mindwendel.Services.SessionService do @session_key_user_id :current_user_id def session_key_current_user_id, do: @session_key_user_id diff --git a/lib/mindwendel_web/controllers/admin/brainstorming_controller.ex b/lib/mindwendel_web/controllers/admin/brainstorming_controller.ex index 75e2e714..eb26ad23 100644 --- a/lib/mindwendel_web/controllers/admin/brainstorming_controller.ex +++ b/lib/mindwendel_web/controllers/admin/brainstorming_controller.ex @@ -1,13 +1,14 @@ defmodule MindwendelWeb.Admin.BrainstormingController do use MindwendelWeb, :controller alias Mindwendel.Brainstormings + alias Mindwendel.Ideas alias Mindwendel.CSVFormatter plug :fetch_user def export(conn, %{"id" => id}) do brainstorming = Brainstormings.get_brainstorming_by!(%{admin_url_id: id}) - ideas = Brainstormings.list_ideas_for_brainstorming(brainstorming.id) + ideas = Ideas.list_ideas_for_brainstorming(brainstorming.id) case get_format(conn) do "csv" -> @@ -33,7 +34,7 @@ defmodule MindwendelWeb.Admin.BrainstormingController do end defp fetch_user(conn, _params) do - current_user_id = MindwendelService.SessionService.get_current_user_id(get_session(conn)) + current_user_id = Mindwendel.Services.SessionService.get_current_user_id(get_session(conn)) current_user = Mindwendel.Accounts.get_user(current_user_id) assign(conn, :current_user, current_user) diff --git a/lib/mindwendel_web/controllers/brainstorming_controller.ex b/lib/mindwendel_web/controllers/brainstorming_controller.ex index a93cb0ab..7e5d72fd 100644 --- a/lib/mindwendel_web/controllers/brainstorming_controller.ex +++ b/lib/mindwendel_web/controllers/brainstorming_controller.ex @@ -5,7 +5,7 @@ defmodule MindwendelWeb.BrainstormingController do def create(conn, %{"brainstorming" => brainstorming_params}) do current_user = - MindwendelService.SessionService.get_current_user_id(conn) + Mindwendel.Services.SessionService.get_current_user_id(conn) |> Accounts.get_or_create_user() case Brainstormings.create_brainstorming(current_user, brainstorming_params) do diff --git a/lib/mindwendel_web/controllers/static_page_controller.ex b/lib/mindwendel_web/controllers/static_page_controller.ex index 6681dfed..a3ea34c6 100644 --- a/lib/mindwendel_web/controllers/static_page_controller.ex +++ b/lib/mindwendel_web/controllers/static_page_controller.ex @@ -8,7 +8,7 @@ defmodule MindwendelWeb.StaticPageController do def home(conn, _params) do current_user = conn - |> MindwendelService.SessionService.get_current_user_id() + |> Mindwendel.Services.SessionService.get_current_user_id() |> Mindwendel.Accounts.get_user() render(conn, "home.html", diff --git a/lib/mindwendel_web/live/brainstorming_live/show.ex b/lib/mindwendel_web/live/brainstorming_live/show.ex index 5fc3495e..2deb72b9 100644 --- a/lib/mindwendel_web/live/brainstorming_live/show.ex +++ b/lib/mindwendel_web/live/brainstorming_live/show.ex @@ -3,13 +3,14 @@ defmodule MindwendelWeb.BrainstormingLive.Show do alias Mindwendel.Accounts alias Mindwendel.Brainstormings + alias Mindwendel.Ideas alias Mindwendel.Brainstormings.Idea @impl true def mount(%{"id" => id}, session, socket) do if connected?(socket), do: Brainstormings.subscribe(id) - current_user_id = MindwendelService.SessionService.get_current_user_id(session) + current_user_id = Mindwendel.Services.SessionService.get_current_user_id(session) brainstorming = Brainstormings.get_brainstorming!(id) @@ -38,8 +39,8 @@ defmodule MindwendelWeb.BrainstormingLive.Show do { :noreply, socket - |> assign(:ideas, Brainstormings.list_ideas_for_brainstorming(brainstorming_id)) - |> assign(:idea, Brainstormings.get_idea!(idea_id)) + |> assign(:ideas, Ideas.list_ideas_for_brainstorming(brainstorming_id)) + |> assign(:idea, Ideas.get_idea!(idea_id)) |> assign(:uri, uri) |> apply_action(socket.assigns.live_action, brainstorming_id: brainstorming_id, @@ -52,7 +53,7 @@ defmodule MindwendelWeb.BrainstormingLive.Show do def handle_params(%{"id" => id}, uri, socket) do {:noreply, socket - |> assign(:ideas, Brainstormings.list_ideas_for_brainstorming(id)) + |> assign(:ideas, Ideas.list_ideas_for_brainstorming(id)) |> assign(:uri, uri) |> apply_action(socket.assigns.live_action, id)} end @@ -60,7 +61,7 @@ defmodule MindwendelWeb.BrainstormingLive.Show do @impl true def handle_info({:idea_added, idea}, socket) do # uses the database to sort and update all ideas, instead of appending the idea to the end of list (which would be more performant) - new_ideas = Brainstormings.list_ideas_for_brainstorming(idea.brainstorming_id) + new_ideas = Ideas.list_ideas_for_brainstorming(idea.brainstorming_id) {:noreply, assign(socket, :ideas, new_ideas)} end @@ -76,7 +77,7 @@ defmodule MindwendelWeb.BrainstormingLive.Show do :noreply, socket |> assign(:brainstorming, Brainstormings.get_brainstorming!(brainstorming.id)) - |> assign(:ideas, Brainstormings.list_ideas_for_brainstorming(brainstorming.id)) + |> assign(:ideas, Ideas.list_ideas_for_brainstorming(brainstorming.id)) } end @@ -118,11 +119,11 @@ defmodule MindwendelWeb.BrainstormingLive.Show do @impl true def handle_event("sort_by_likes", %{"id" => id}, socket) do - {:noreply, assign(socket, :ideas, Brainstormings.list_ideas_for_brainstorming(id))} + {:noreply, assign(socket, :ideas, Ideas.list_ideas_for_brainstorming(id))} end def handle_event("sort_by_label", %{"id" => id}, socket) do - {:noreply, assign(socket, :ideas, Brainstormings.sort_ideas_by_labels(id))} + {:noreply, assign(socket, :ideas, Ideas.sort_ideas_by_labels(id))} end def handle_event("handle_hotkey_i", _, socket) do diff --git a/lib/mindwendel_web/live/idea_live/form_component.ex b/lib/mindwendel_web/live/idea_live/form_component.ex index 4ec0a45b..992301d1 100644 --- a/lib/mindwendel_web/live/idea_live/form_component.ex +++ b/lib/mindwendel_web/live/idea_live/form_component.ex @@ -1,11 +1,11 @@ defmodule MindwendelWeb.IdeaLive.FormComponent do use MindwendelWeb, :live_component - alias Mindwendel.Brainstormings + alias Mindwendel.Ideas @impl true def update(%{idea: idea} = assigns, socket) do - changeset = Brainstormings.change_idea(idea) + changeset = Ideas.change_idea(idea) {:ok, socket @@ -17,7 +17,7 @@ defmodule MindwendelWeb.IdeaLive.FormComponent do def handle_event("validate", %{"idea" => idea_params}, socket) do changeset = socket.assigns.idea - |> Brainstormings.change_idea(idea_params) + |> Ideas.change_idea(idea_params) |> Map.put(:action, :validate) {:noreply, assign(socket, :changeset, changeset)} @@ -28,12 +28,12 @@ defmodule MindwendelWeb.IdeaLive.FormComponent do end defp save_idea(socket, :update, idea_params) do - idea = Brainstormings.get_idea!(idea_params["id"]) + idea = Ideas.get_idea!(idea_params["id"]) %{current_user: current_user, brainstorming: brainstorming} = socket.assigns if current_user.id in [idea.user_id | brainstorming.moderating_users |> Enum.map(& &1.id)] do - case Brainstormings.update_idea( + case Ideas.update_idea( idea, Map.put(idea_params, "user_id", idea.user_id || current_user.id) ) do @@ -54,9 +54,7 @@ defmodule MindwendelWeb.IdeaLive.FormComponent do username: idea_params["username"] }) - case Brainstormings.create_idea( - Map.put(idea_params, "user_id", socket.assigns.current_user.id) - ) do + case Ideas.create_idea(Map.put(idea_params, "user_id", socket.assigns.current_user.id)) do {:ok, _idea} -> {:noreply, socket diff --git a/lib/mindwendel_web/live/idea_live/index_component.ex b/lib/mindwendel_web/live/idea_live/index_component.ex index 2b3dc466..9a785522 100644 --- a/lib/mindwendel_web/live/idea_live/index_component.ex +++ b/lib/mindwendel_web/live/idea_live/index_component.ex @@ -1,11 +1,13 @@ defmodule MindwendelWeb.IdeaLive.IndexComponent do use MindwendelWeb, :live_component - alias Mindwendel.Brainstormings + alias Mindwendel.Ideas + alias Mindwendel.IdeaLabels + alias Mindwendel.Likes @impl true def handle_event("edit", %{"id" => id}, socket) do - idea = Brainstormings.get_idea!(id) + idea = Ideas.get_idea!(id) {:noreply, socket @@ -16,12 +18,12 @@ defmodule MindwendelWeb.IdeaLive.IndexComponent do @impl true def handle_event("delete", %{"id" => id}, socket) do - idea = Brainstormings.get_idea!(id) + idea = Ideas.get_idea!(id) %{current_user: current_user, brainstorming: brainstorming} = socket.assigns if current_user.id in [idea.user_id | brainstorming.moderating_users |> Enum.map(& &1.id)] do - {:ok, _} = Brainstormings.delete_idea(idea) + {:ok, _} = Ideas.delete_idea(idea) end # broadcast will take care of the removal from the list @@ -30,14 +32,14 @@ defmodule MindwendelWeb.IdeaLive.IndexComponent do @impl true def handle_event("like", %{"id" => id}, socket) do - Brainstormings.add_like(id, socket.assigns.current_user.id) + Likes.add_like(id, socket.assigns.current_user.id) {:noreply, socket} end @impl true def handle_event("unlike", %{"id" => id}, socket) do - Brainstormings.delete_like(id, socket.assigns.current_user.id) + Likes.delete_like(id, socket.assigns.current_user.id) {:noreply, socket} end @@ -50,10 +52,10 @@ defmodule MindwendelWeb.IdeaLive.IndexComponent do }, socket ) do - idea = Brainstormings.get_idea!(idea_id) - idea_label = Brainstormings.get_idea_label(idea_label_id) + idea = Ideas.get_idea!(idea_id) + idea_label = IdeaLabels.get_idea_label(idea_label_id) - case(Brainstormings.add_idea_label_to_idea(idea, idea_label)) do + case(IdeaLabels.add_idea_label_to_idea(idea, idea_label)) do {:ok, _idea} -> {:noreply, socket} @@ -70,10 +72,10 @@ defmodule MindwendelWeb.IdeaLive.IndexComponent do }, socket ) do - idea = Brainstormings.get_idea!(idea_id) - idea_label = Brainstormings.get_idea_label(idea_label_id) + idea = Ideas.get_idea!(idea_id) + idea_label = IdeaLabels.get_idea_label(idea_label_id) - case(Brainstormings.remove_idea_label_from_idea(idea, idea_label)) do + case(IdeaLabels.remove_idea_label_from_idea(idea, idea_label)) do {:ok, _idea} -> {:noreply, socket} diff --git a/lib/mindwendel_web/live/idea_live/index_component.html.heex b/lib/mindwendel_web/live/idea_live/index_component.html.heex index 0046214f..56f382c6 100644 --- a/lib/mindwendel_web/live/idea_live/index_component.html.heex +++ b/lib/mindwendel_web/live/idea_live/index_component.html.heex @@ -60,7 +60,7 @@
<%= length(idea.likes) %> - <%= unless Mindwendel.Brainstormings.exists_like_for_idea?(idea.id, @current_user.id) do %> + <%= unless Mindwendel.Likes.exists_like_for_idea?(idea.id, @current_user.id) do %> <%= link to: "#", phx_click: "like", phx_target: @myself, phx_value_id: idea.id, title: 'Like' do %> <% end %> diff --git a/lib/mindwendel_web/plugs/set_session_device_id.ex b/lib/mindwendel_web/plugs/set_session_device_id.ex index 2199b4e2..dd1036d3 100644 --- a/lib/mindwendel_web/plugs/set_session_device_id.ex +++ b/lib/mindwendel_web/plugs/set_session_device_id.ex @@ -6,9 +6,9 @@ defmodule Mindwendel.Plugs.SetSessionUserId do # @impl true def call(conn, _opts) do - case MindwendelService.SessionService.get_current_user_id(conn) do + case Mindwendel.Services.SessionService.get_current_user_id(conn) do nil -> - MindwendelService.SessionService.set_current_user_id(conn) + Mindwendel.Services.SessionService.set_current_user_id(conn) _ -> conn diff --git a/lib/mindwendel_web/views/admin/brainstorming.ex b/lib/mindwendel_web/views/admin/brainstorming.ex index cab748ac..bb9e6072 100644 --- a/lib/mindwendel_web/views/admin/brainstorming.ex +++ b/lib/mindwendel_web/views/admin/brainstorming.ex @@ -1,9 +1,9 @@ defmodule MindwendelWeb.Admin.BrainstormingView do use MindwendelWeb, :view - alias Mindwendel.Brainstormings + alias Mindwendel.Likes def count_likes_for_idea(idea) do - Brainstormings.count_likes_for_idea(idea) + Likes.count_likes_for_idea(idea) end def brainstorming_available_until(brainstorming) do diff --git a/priv/gettext/de/LC_MESSAGES/default.po b/priv/gettext/de/LC_MESSAGES/default.po index e67baf29..f8f04f1a 100644 --- a/priv/gettext/de/LC_MESSAGES/default.po +++ b/priv/gettext/de/LC_MESSAGES/default.po @@ -26,12 +26,12 @@ msgstr "Wie können wir ..." msgid "Ready?" msgstr "Fertig?" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:111 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:112 #, elixir-autogen, elixir-format msgid "%{name} - Edit" msgstr "%{name} - Editieren" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:97 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:98 #, elixir-autogen, elixir-format msgid "%{name} - New Idea" msgstr "%{name} - Neue Idee" @@ -92,13 +92,13 @@ msgstr "Export als HTML" msgid "Got stuck? Try inspirational teasers!" msgstr "Keine Ideen? Hier gibts Gedankenanstöße!" -#: lib/mindwendel_web/live/idea_live/form_component.ex:63 +#: lib/mindwendel_web/live/idea_live/form_component.ex:61 #, elixir-autogen, elixir-format msgid "Idea created successfully" msgstr "Idee erstellt" #: lib/mindwendel_web/live/brainstorming_live/show.html.heex:25 -#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:117 +#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:121 #, elixir-autogen, elixir-format msgid "New Idea" msgstr "Neue Idee" @@ -123,7 +123,7 @@ msgstr "Neue Idee (Hotkey: i)" msgid "No ideas brainstormed" msgstr "Bisher keine Ideen" -#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:120 +#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:124 #, elixir-autogen, elixir-format msgid "Open new idea page (Hotkey: i)" msgstr "Öffne neue Ideen Dialog (Hotkey: i)" @@ -180,7 +180,7 @@ msgstr "mindwendel konnte nicht gefunden werden." msgid "Something went wrong when creating a brainstorming. Please try again." msgstr "Leider gab es einen Fehler beim Erstellen des Brainstormings. Bitte probiere es erneut." -#: lib/mindwendel_web/controllers/admin/brainstorming_controller.ex:31 +#: lib/mindwendel_web/controllers/admin/brainstorming_controller.ex:32 #, elixir-autogen, elixir-format msgid "Successfully deleted brainstorming." msgstr "Brainstorming erfolgreich gelöscht" diff --git a/priv/gettext/default.pot b/priv/gettext/default.pot index 2aeb2f6e..4d12adf2 100644 --- a/priv/gettext/default.pot +++ b/priv/gettext/default.pot @@ -25,12 +25,12 @@ msgstr "" msgid "Ready?" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:111 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:112 #, elixir-autogen, elixir-format msgid "%{name} - Edit" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:97 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:98 #, elixir-autogen, elixir-format msgid "%{name} - New Idea" msgstr "" @@ -91,7 +91,7 @@ msgstr "" msgid "Got stuck? Try inspirational teasers!" msgstr "" -#: lib/mindwendel_web/live/idea_live/form_component.ex:63 +#: lib/mindwendel_web/live/idea_live/form_component.ex:61 #, elixir-autogen, elixir-format msgid "Idea created successfully" msgstr "" @@ -179,7 +179,7 @@ msgstr "" msgid "Something went wrong when creating a brainstorming. Please try again." msgstr "" -#: lib/mindwendel_web/controllers/admin/brainstorming_controller.ex:31 +#: lib/mindwendel_web/controllers/admin/brainstorming_controller.ex:32 #, elixir-autogen, elixir-format msgid "Successfully deleted brainstorming." msgstr "" diff --git a/priv/gettext/en/LC_MESSAGES/default.po b/priv/gettext/en/LC_MESSAGES/default.po index 633cf5ed..4ae1dfc8 100644 --- a/priv/gettext/en/LC_MESSAGES/default.po +++ b/priv/gettext/en/LC_MESSAGES/default.po @@ -26,12 +26,12 @@ msgstr "" msgid "Ready?" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:111 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:112 #, elixir-autogen, elixir-format msgid "%{name} - Edit" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.ex:97 +#: lib/mindwendel_web/live/brainstorming_live/show.ex:98 #, elixir-autogen, elixir-format msgid "%{name} - New Idea" msgstr "" @@ -92,13 +92,13 @@ msgstr "" msgid "Got stuck? Try inspirational teasers!" msgstr "" -#: lib/mindwendel_web/live/idea_live/form_component.ex:63 +#: lib/mindwendel_web/live/idea_live/form_component.ex:61 #, elixir-autogen, elixir-format msgid "Idea created successfully" msgstr "" #: lib/mindwendel_web/live/brainstorming_live/show.html.heex:25 -#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:117 +#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:121 #, elixir-autogen, elixir-format msgid "New Idea" msgstr "" @@ -123,7 +123,7 @@ msgstr "" msgid "No ideas brainstormed" msgstr "" -#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:120 +#: lib/mindwendel_web/live/brainstorming_live/show.html.heex:124 #, elixir-autogen, elixir-format msgid "Open new idea page (Hotkey: i)" msgstr "" @@ -180,7 +180,7 @@ msgstr "" msgid "Something went wrong when creating a brainstorming. Please try again." msgstr "" -#: lib/mindwendel_web/controllers/admin/brainstorming_controller.ex:31 +#: lib/mindwendel_web/controllers/admin/brainstorming_controller.ex:32 #, elixir-autogen, elixir-format msgid "Successfully deleted brainstorming." msgstr "" diff --git a/test/mindwendel/brainstormings_test.exs b/test/mindwendel/brainstormings_test.exs index 3121e214..22a2ba01 100644 --- a/test/mindwendel/brainstormings_test.exs +++ b/test/mindwendel/brainstormings_test.exs @@ -5,6 +5,7 @@ defmodule Mindwendel.BrainstormingsTest do alias Mindwendel.Factory alias Mindwendel.Brainstormings + alias Mindwendel.IdeaLabels alias Mindwendel.Brainstormings.Brainstorming alias Mindwendel.Brainstormings.Idea alias Mindwendel.Brainstormings.Like @@ -87,157 +88,6 @@ defmodule Mindwendel.BrainstormingsTest do end end - describe "list_ideas_for_brainstorming" do - test "orders by like count", %{brainstorming: brainstorming, user: user, idea: idea} do - first_idea = Factory.insert!(:idea, brainstorming: brainstorming) - third_idea = Factory.insert!(:idea, brainstorming: brainstorming) - second_idea = Factory.insert!(:idea, brainstorming: brainstorming) - - another_user = Factory.insert!(:user) - - Brainstormings.add_like(first_idea.id, user.id) - Brainstormings.add_like(first_idea.id, another_user.id) - Brainstormings.add_like(second_idea.id, user.id) - - ids = - Enum.map(Brainstormings.list_ideas_for_brainstorming(brainstorming.id), fn x -> x.id end) - - assert ids == [first_idea.id, second_idea.id, third_idea.id, idea.id] - end - - test "orders by date if like count is equal", %{ - brainstorming: brainstorming, - user: user, - idea: idea - } do - older_idea = - Factory.insert!(:idea, - brainstorming: brainstorming, - inserted_at: ~N[2021-01-15 15:04:30] - ) - - younger_idea = - Factory.insert!(:idea, - brainstorming: brainstorming, - inserted_at: ~N[2021-01-15 15:05:30] - ) - - Brainstormings.add_like(older_idea.id, user.id) - Brainstormings.add_like(younger_idea.id, user.id) - - ids = - Enum.map(Brainstormings.list_ideas_for_brainstorming(brainstorming.id), fn x -> x.id end) - - assert ids == [younger_idea.id, older_idea.id, idea.id] - end - end - - describe "exists_like_for_idea?" do - test "returns true if like is given", %{idea: idea, user: user} do - Factory.insert!(:like, %{idea_id: idea.id, user_id: user.id}) - assert Brainstormings.exists_like_for_idea?(idea.id, user.id) == true - end - - test "returns false if like is not given", %{idea: idea, user: user} do - assert Brainstormings.exists_like_for_idea?(idea.id, user.id) == false - end - end - - describe "increment_likes_for_idea" do - test "adds a like", %{idea: idea, user: user} do - Brainstormings.add_like(idea.id, user.id) - count = idea |> assoc(:likes) |> Repo.aggregate(:count, :id) - assert count == 1 - end - - test "can't add a second like", %{idea: idea, user: user} do - Factory.insert!(:like, %{idea_id: idea.id, user_id: user.id}) - Brainstormings.add_like(idea.id, user.id) - count = idea |> assoc(:likes) |> Repo.aggregate(:count, :id) - assert count == 1 - end - end - - describe "delete_likes" do - @tag individual_test: "true" - test "deletes a like", %{like: like} do - count = like.idea |> assoc(:likes) |> Repo.aggregate(:count, :id) - assert count == 1 - - # delete like: - Brainstormings.delete_like(like.idea.id, like.user.id) - - count = like.idea |> assoc(:likes) |> Repo.aggregate(:count, :id) - assert count == 0 - end - end - - describe "count_likes_for_idea" do - test "count likes", %{like: like} do - assert Ecto.assoc(like, :idea) - |> Repo.one() - |> Brainstormings.count_likes_for_idea() == 1 - end - end - - describe "sort_ideas_by_labels" do - test "sorts without ideas" do - brainstorming_without_ideas = Factory.insert!(:brainstorming) - - ideas_sorted_by_labels = Brainstormings.sort_ideas_by_labels(brainstorming_without_ideas.id) - - assert ideas_sorted_by_labels |> Enum.empty?() - assert ideas_sorted_by_labels == [] - end - - test "sorts unlabelled ideas based on inserted_at", %{ - brainstorming: brainstorming, - idea: idea_old - } do - idea_young = Factory.insert!(:idea, %{brainstorming: brainstorming}) - - ideas_sorted_by_labels = Brainstormings.sort_ideas_by_labels(brainstorming.id) - - assert ideas_sorted_by_labels |> Enum.map(& &1.id) == [idea_young.id, idea_old.id] - end - - test "sorts labelled ideas based on label position order and inserted_at", %{ - brainstorming: brainstorming, - idea: idea_without_label - } do - brainstorming = brainstorming |> Repo.preload([:labels]) - - idea_with_1st_label_older = - Factory.insert!(:idea, %{ - brainstorming: brainstorming, - label: Enum.at(brainstorming.labels, 0) - }) - - idea_with_second_label = - Factory.insert!(:idea, %{ - brainstorming: brainstorming, - label: Enum.at(brainstorming.labels, 1) - }) - - # Created 10 seconds later than idea_with_1st_label_older - idea_with_1st_label_younger = - Factory.insert!(:idea, %{ - brainstorming: brainstorming, - inserted_at: NaiveDateTime.add(idea_with_1st_label_older.inserted_at, 10), - label: Enum.at(brainstorming.labels, 0) - }) - - ideas_sorted_by_labels = Brainstormings.sort_ideas_by_labels(brainstorming.id) - - assert Enum.map(ideas_sorted_by_labels, & &1.id) == [ - idea_with_1st_label_younger.id, - idea_with_1st_label_older.id, - idea_with_second_label.id, - idea_without_label.id - ] - end - end - describe "delete_old_brainstormings" do test "removes the brainstorming" do old_brainstorming = Factory.insert!(:brainstorming, inserted_at: ~N[2021-01-01 10:00:00]) @@ -334,7 +184,7 @@ defmodule Mindwendel.BrainstormingsTest do like = Factory.insert!(:like, idea: idea) {:ok, idea} = - Brainstormings.add_idea_label_to_idea(idea, Enum.at(brainstorming.labels, 0)) + IdeaLabels.add_idea_label_to_idea(idea, Enum.at(brainstorming.labels, 0)) idea = idea |> Repo.preload([:idea_labels]) diff --git a/test/mindwendel/brainstormings_idea_test.exs b/test/mindwendel/idea_labels_test.exs similarity index 78% rename from test/mindwendel/brainstormings_idea_test.exs rename to test/mindwendel/idea_labels_test.exs index 6a1ec5b7..24525604 100644 --- a/test/mindwendel/brainstormings_idea_test.exs +++ b/test/mindwendel/idea_labels_test.exs @@ -1,8 +1,9 @@ -defmodule Mindwendel.BrainstormingsIdeaTest do +defmodule Mindwendel.IdeaLabelsTest do use Mindwendel.DataCase alias Mindwendel.Factory - alias Mindwendel.Brainstormings + alias Mindwendel.Ideas + alias Mindwendel.IdeaLabels alias Mindwendel.Brainstormings.IdeaLabel alias Mindwendel.Brainstormings.IdeaIdeaLabel @@ -16,14 +17,14 @@ defmodule Mindwendel.BrainstormingsIdeaTest do describe "#add_idea_label_to_idea" do test "adds IdeaLabel to Idea", %{idea_label: idea_label, idea: idea} do - {:ok, idea_changed} = Brainstormings.add_idea_label_to_idea(idea, idea_label) + {:ok, idea_changed} = IdeaLabels.add_idea_label_to_idea(idea, idea_label) assert idea_changed.idea_labels |> Enum.count() == 1 assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 1 end test "creates one IdeaIdeaLabel", %{idea_label: idea_label, idea: idea} do - {:ok, _idea_changed} = Brainstormings.add_idea_label_to_idea(idea, idea_label) + {:ok, _idea_changed} = IdeaLabels.add_idea_label_to_idea(idea, idea_label) assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 1 @@ -35,7 +36,7 @@ defmodule Mindwendel.BrainstormingsIdeaTest do test "does not create additional IdeaLabel", %{idea_label: idea_label, idea: idea} do assert Repo.all(IdeaLabel) |> Enum.count() == 1 - {:ok, _idea_changed} = Brainstormings.add_idea_label_to_idea(idea, idea_label) + {:ok, _idea_changed} = IdeaLabels.add_idea_label_to_idea(idea, idea_label) assert Repo.all(IdeaLabel) |> Enum.count() == 1 assert Repo.one(IdeaLabel) == idea_label @@ -44,8 +45,8 @@ defmodule Mindwendel.BrainstormingsIdeaTest do @tag :skip test "does not add the same IdeaLabel twice to Idea", %{idea_label: idea_label, idea: idea} do # Calling this method twice does not fail and does not create duplicates - {:ok, idea_after_method_call_1} = Brainstormings.add_idea_label_to_idea(idea, idea_label) - {:ok, idea_after_method_call_2} = Brainstormings.add_idea_label_to_idea(idea, idea_label) + {:ok, idea_after_method_call_1} = IdeaLabels.add_idea_label_to_idea(idea, idea_label) + {:ok, idea_after_method_call_2} = IdeaLabels.add_idea_label_to_idea(idea, idea_label) # There should still be only one IdeaIdeaLabel assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 1 @@ -66,14 +67,14 @@ defmodule Mindwendel.BrainstormingsIdeaTest do }) {:error, _changeset} = - Brainstormings.add_idea_label_to_idea(idea, idea_label_from_another_brainstorming) + IdeaLabels.add_idea_label_to_idea(idea, idea_label_from_another_brainstorming) end @tag :skip test "update idea_labels", %{idea: idea} do idea = Repo.preload(idea, :idea_labels) _idea_label = idea.brainstorming.labels |> Enum.at(0) - Brainstormings.update_idea(idea, %{idea_labels: []}) + Ideas.update_idea(idea, %{idea_labels: []}) assert Enum.empty?(idea.idea_labels) end @@ -90,7 +91,7 @@ defmodule Mindwendel.BrainstormingsIdeaTest do idea = Repo.preload(idea, [:idea_labels, :idea_idea_labels]) idea_label = idea.brainstorming.labels |> Enum.at(0) - Brainstormings.add_idea_label_to_idea(idea, idea_label) + IdeaLabels.add_idea_label_to_idea(idea, idea_label) assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 1 assert Repo.one(IdeaIdeaLabel).idea_id == idea.id @@ -107,13 +108,13 @@ defmodule Mindwendel.BrainstormingsIdeaTest do describe "#delete_idea_label_from_idea" do setup %{idea_label: idea_label, idea: idea} do - {:ok, idea} = Brainstormings.add_idea_label_to_idea(idea, idea_label) + {:ok, idea} = IdeaLabels.add_idea_label_to_idea(idea, idea_label) assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 1 %{idea: idea} end test "removes successfully IdeaLabel from Idea", %{idea_label: idea_label, idea: idea} do - Brainstormings.remove_idea_label_from_idea(idea, idea_label) + IdeaLabels.remove_idea_label_from_idea(idea, idea_label) assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 0 end @@ -122,8 +123,8 @@ defmodule Mindwendel.BrainstormingsIdeaTest do idea: idea } do # Calling this method twice does not fail - Brainstormings.remove_idea_label_from_idea(idea, idea_label) - Brainstormings.remove_idea_label_from_idea(idea, idea_label) + IdeaLabels.remove_idea_label_from_idea(idea, idea_label) + IdeaLabels.remove_idea_label_from_idea(idea, idea_label) assert Repo.all(IdeaIdeaLabel) |> Enum.count() == 0 end diff --git a/test/mindwendel/idea_test.exs b/test/mindwendel/idea_test.exs index 01ac6c99..984cef4e 100644 --- a/test/mindwendel/idea_test.exs +++ b/test/mindwendel/idea_test.exs @@ -2,7 +2,7 @@ defmodule Mindwendel.IdeaTest do use Mindwendel.DataCase alias Mindwendel.Factory - alias Mindwendel.Brainstormings + alias Mindwendel.Ideas alias Mindwendel.Brainstormings.Idea describe("Factory.build(:idea)") do @@ -38,7 +38,7 @@ defmodule Mindwendel.IdeaTest do end test "saves object in database" do - assert Brainstormings.list_ideas() |> Enum.count() == 1 + assert Ideas.list_ideas() |> Enum.count() == 1 end end @@ -75,7 +75,7 @@ defmodule Mindwendel.IdeaTest do end test "update idea_labels", %{idea: idea} do - Brainstormings.update_idea(idea, %{idea_labels: []}) + Ideas.update_idea(idea, %{idea_labels: []}) assert Enum.empty?(idea.idea_labels) end diff --git a/test/mindwendel/ideas_test.exs b/test/mindwendel/ideas_test.exs new file mode 100644 index 00000000..278914b3 --- /dev/null +++ b/test/mindwendel/ideas_test.exs @@ -0,0 +1,123 @@ +defmodule Mindwendel.IdeasTest do + use Mindwendel.DataCase + alias Mindwendel.Factory + + alias Mindwendel.Likes + alias Mindwendel.Ideas + + setup do + user = Factory.insert!(:user) + brainstorming = Factory.insert!(:brainstorming, users: [user]) + + %{ + brainstorming: brainstorming, + idea: + Factory.insert!(:idea, brainstorming: brainstorming, inserted_at: ~N[2021-01-01 15:04:30]), + user: user, + like: Factory.insert!(:like, :with_idea_and_user) + } + end + + describe "list_ideas_for_brainstorming" do + test "orders by like count", %{brainstorming: brainstorming, user: user, idea: idea} do + first_idea = Factory.insert!(:idea, brainstorming: brainstorming) + third_idea = Factory.insert!(:idea, brainstorming: brainstorming) + second_idea = Factory.insert!(:idea, brainstorming: brainstorming) + + another_user = Factory.insert!(:user) + + Likes.add_like(first_idea.id, user.id) + Likes.add_like(first_idea.id, another_user.id) + Likes.add_like(second_idea.id, user.id) + + ids = + Enum.map(Ideas.list_ideas_for_brainstorming(brainstorming.id), fn x -> x.id end) + + assert ids == [first_idea.id, second_idea.id, third_idea.id, idea.id] + end + + test "orders by date if like count is equal", %{ + brainstorming: brainstorming, + user: user, + idea: idea + } do + older_idea = + Factory.insert!(:idea, + brainstorming: brainstorming, + inserted_at: ~N[2021-01-15 15:04:30] + ) + + younger_idea = + Factory.insert!(:idea, + brainstorming: brainstorming, + inserted_at: ~N[2021-01-15 15:05:30] + ) + + Likes.add_like(older_idea.id, user.id) + Likes.add_like(younger_idea.id, user.id) + + ids = + Enum.map(Ideas.list_ideas_for_brainstorming(brainstorming.id), fn x -> x.id end) + + assert ids == [younger_idea.id, older_idea.id, idea.id] + end + end + + describe "sort_ideas_by_labels" do + test "sorts without ideas" do + brainstorming_without_ideas = Factory.insert!(:brainstorming) + + ideas_sorted_by_labels = Ideas.sort_ideas_by_labels(brainstorming_without_ideas.id) + + assert ideas_sorted_by_labels |> Enum.empty?() + assert ideas_sorted_by_labels == [] + end + + test "sorts unlabelled ideas based on inserted_at", %{ + brainstorming: brainstorming, + idea: idea_old + } do + idea_young = Factory.insert!(:idea, %{brainstorming: brainstorming}) + + ideas_sorted_by_labels = Ideas.sort_ideas_by_labels(brainstorming.id) + + assert ideas_sorted_by_labels |> Enum.map(& &1.id) == [idea_young.id, idea_old.id] + end + + test "sorts labelled ideas based on label position order and inserted_at", %{ + brainstorming: brainstorming, + idea: idea_without_label + } do + brainstorming = brainstorming |> Repo.preload([:labels]) + + idea_with_1st_label_older = + Factory.insert!(:idea, %{ + brainstorming: brainstorming, + label: Enum.at(brainstorming.labels, 0) + }) + + idea_with_second_label = + Factory.insert!(:idea, %{ + brainstorming: brainstorming, + label: Enum.at(brainstorming.labels, 1) + }) + + # Created 10 seconds later than idea_with_1st_label_older + idea_with_1st_label_younger = + Factory.insert!(:idea, %{ + brainstorming: brainstorming, + inserted_at: NaiveDateTime.add(idea_with_1st_label_older.inserted_at, 10), + label: Enum.at(brainstorming.labels, 0) + }) + + ideas_sorted_by_labels = Ideas.sort_ideas_by_labels(brainstorming.id) + + assert Enum.map(ideas_sorted_by_labels, & &1.id) == [ + idea_with_1st_label_younger.id, + idea_with_1st_label_older.id, + idea_with_second_label.id, + idea_without_label.id + ] + end + end +end diff --git a/test/mindwendel/likes_test.exs b/test/mindwendel/likes_test.exs new file mode 100644 index 00000000..b6e356ce --- /dev/null +++ b/test/mindwendel/likes_test.exs @@ -0,0 +1,66 @@ +defmodule Mindwendel.LikesTest do + use Mindwendel.DataCase + alias Mindwendel.Factory + alias Mindwendel.Likes + + setup do + user = Factory.insert!(:user) + brainstorming = Factory.insert!(:brainstorming, users: [user]) + + %{ + brainstorming: brainstorming, + idea: + Factory.insert!(:idea, brainstorming: brainstorming, inserted_at: ~N[2021-01-01 15:04:30]), + user: user, + like: Factory.insert!(:like, :with_idea_and_user) + } + end + + describe "exists_like_for_idea?" do + test "returns true if like is given", %{idea: idea, user: user} do + Factory.insert!(:like, %{idea_id: idea.id, user_id: user.id}) + assert Likes.exists_like_for_idea?(idea.id, user.id) == true + end + + test "returns false if like is not given", %{idea: idea, user: user} do + assert Likes.exists_like_for_idea?(idea.id, user.id) == false + end + end + + describe "increment_likes_for_idea" do + test "adds a like", %{idea: idea, user: user} do + Likes.add_like(idea.id, user.id) + count = idea |> assoc(:likes) |> Repo.aggregate(:count, :id) + assert count == 1 + end + + test "can't add a second like", %{idea: idea, user: user} do + Factory.insert!(:like, %{idea_id: idea.id, user_id: user.id}) + Likes.add_like(idea.id, user.id) + count = idea |> assoc(:likes) |> Repo.aggregate(:count, :id) + assert count == 1 + end + end + + describe "delete_likes" do + @tag individual_test: "true" + test "deletes a like", %{like: like} do + count = like.idea |> assoc(:likes) |> Repo.aggregate(:count, :id) + assert count == 1 + + # delete like: + Likes.delete_like(like.idea.id, like.user.id) + + count = like.idea |> assoc(:likes) |> Repo.aggregate(:count, :id) + assert count == 0 + end + end + + describe "count_likes_for_idea" do + test "count likes", %{like: like} do + assert Ecto.assoc(like, :idea) + |> Repo.one() + |> Likes.count_likes_for_idea() == 1 + end + end +end diff --git a/test/mindwendel_web/channels/brainstorming_channel_test.exs b/test/mindwendel_web/channels/brainstorming_channel_test.exs index 964bc598..69c6356a 100644 --- a/test/mindwendel_web/channels/brainstorming_channel_test.exs +++ b/test/mindwendel_web/channels/brainstorming_channel_test.exs @@ -3,6 +3,7 @@ defmodule MindwendelWeb.BrainstormingChannelTest do alias Mindwendel.Factory alias Mindwendel.Brainstormings + alias Mindwendel.Ideas setup do %{ @@ -15,7 +16,7 @@ defmodule MindwendelWeb.BrainstormingChannelTest do idea = Factory.insert!(:idea, brainstorming: brainstorming) Brainstormings.subscribe(brainstorming.id) - Brainstormings.update_idea(idea, %{body: "lalala"}) + Ideas.update_idea(idea, %{body: "lalala"}) assert_received {:idea_updated, idea_updated} # It should not be a %Ecto.Association.NotLoaded assert idea_updated.idea_labels == [] @@ -26,7 +27,7 @@ defmodule MindwendelWeb.BrainstormingChannelTest do other_brainstorming = Factory.insert!(:brainstorming) Brainstormings.subscribe(other_brainstorming.id) - Brainstormings.update_idea(idea, %{body: "lalala"}) + Ideas.update_idea(idea, %{body: "lalala"}) refute_received {:idea_updated, _} end end diff --git a/test/mindwendel_web/controllers/static_page_controller_test.exs b/test/mindwendel_web/controllers/static_page_controller_test.exs index f37a946e..921330b6 100644 --- a/test/mindwendel_web/controllers/static_page_controller_test.exs +++ b/test/mindwendel_web/controllers/static_page_controller_test.exs @@ -12,7 +12,7 @@ defmodule MindwendelWeb.StaticPageControllerTest do test "sets current_user_id in session", %{conn: conn} do conn = get(conn, Routes.static_page_path(conn, :home)) - refute MindwendelService.SessionService.get_current_user_id(conn) == nil + refute Mindwendel.Services.SessionService.get_current_user_id(conn) == nil end test "does not contain recent brainstormings", %{conn: conn} do @@ -35,7 +35,7 @@ defmodule MindwendelWeb.StaticPageControllerTest do conn = init_test_session(conn, %{ - MindwendelService.SessionService.session_key_current_user_id() => user.id + Mindwendel.Services.SessionService.session_key_current_user_id() => user.id }) conn = get(conn, Routes.static_page_path(conn, :home)) @@ -50,7 +50,7 @@ defmodule MindwendelWeb.StaticPageControllerTest do conn = init_test_session(conn, %{ - MindwendelService.SessionService.session_key_current_user_id() => user.id + Mindwendel.Services.SessionService.session_key_current_user_id() => user.id }) conn = get(conn, Routes.static_page_path(conn, :home)) diff --git a/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs b/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs index 8648869d..8ac70619 100644 --- a/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs +++ b/test/mindwendel_web/live/brainstorming_live/show_idea_edit_test.exs @@ -139,9 +139,9 @@ defmodule MindwendelWeb.BrainstormingLive.ShowIdeaEditTest do |> element(".card-body-mindwendel-idea", new_idea_body) |> has_element? - assert Mindwendel.Brainstormings.get_idea!(idea.id).user_id - assert moderator_user.id != Mindwendel.Brainstormings.get_idea!(idea.id).user_id - assert ^user_id = Mindwendel.Brainstormings.get_idea!(idea.id).user_id + assert Mindwendel.Ideas.get_idea!(idea.id).user_id + assert moderator_user.id != Mindwendel.Ideas.get_idea!(idea.id).user_id + assert ^user_id = Mindwendel.Ideas.get_idea!(idea.id).user_id end defp html_selector_button_idea_edit_link do