Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: refactoring opportunities #275

Merged
merged 3 commits into from
Mar 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 1 addition & 283 deletions lib/mindwendel/brainstormings.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.

Expand Down Expand Up @@ -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.

Expand All @@ -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{ ... }} =
Expand Down Expand Up @@ -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.

Expand Down
4 changes: 2 additions & 2 deletions lib/mindwendel/csv_formatter.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Mindwendel.CSVFormatter do
alias Mindwendel.Brainstormings
alias Mindwendel.Likes

def ideas_to_csv(ideas) do
[["idea", "username", "likes"]]
Expand All @@ -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)
]
)
)
Expand Down
51 changes: 51 additions & 0 deletions lib/mindwendel/idea_labels.ex
Original file line number Diff line number Diff line change
@@ -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
Loading
Loading