Skip to content
Open
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
106 changes: 106 additions & 0 deletions lib/atlas/feedbacks.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
defmodule Atlas.Feedbacks do
@moduledoc """
The Feedbacks context.
"""

use Atlas.Context
alias Atlas.Repo

alias Atlas.Feedbacks.Feedback

@doc """
Returns the list of feedbacks.

## Examples

iex> list_feedbacks()
[%Feedback{}, ...]

"""
def list_feedbacks(opts \\ []) do
Feedback
|> apply_filters(opts)
|> Repo.all()
end

@doc """
Gets a single feedback.

Raises `Ecto.NoResultsError` if the Feedback does not exist.

## Examples

iex> get_feedback!(123)
%Feedback{}

iex> get_feedback!(456)
** (Ecto.NoResultsError)

"""
def get_feedback!(id), do: Repo.get(Feedback, id)

@doc """
Creates a feedback.

## Examples

iex> create_feedback(%{field: value})
{:ok, %Feedback{}}

iex> create_feedback(%{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def create_feedback(attrs \\ %{}) do
%Feedback{}
|> Feedback.changeset(attrs)
|> Repo.insert()
end

@doc """
Updates a feedback.

## Examples

iex> update_feedback(feedback, %{field: new_value})
{:ok, %Feedback{}}

iex> update_feedback(feedback, %{field: bad_value})
{:error, %Ecto.Changeset{}}

"""
def update_feedback(%Feedback{} = feedback, attrs) do
feedback
|> Feedback.changeset(attrs)
|> Repo.update()
end

@doc """
Deletes a feedback.

## Examples

iex> delete_feedback(feedback)
{:ok, %Feedback{}}

iex> delete_feedback(feedback)
{:error, %Ecto.Changeset{}}

"""
def delete_feedback(%Feedback{} = feedback) do
Repo.delete(feedback)
end

@doc """
Returns an `%Ecto.Changeset{}` for tracking feedback changes.

## Examples

iex> change_feedback(feedback)
%Ecto.Changeset{data: %Feedback{}}

"""
def change_feedback(%Feedback{} = feedback, attrs \\ %{}) do
Feedback.changeset(feedback, attrs)
end
end
26 changes: 26 additions & 0 deletions lib/atlas/feedbacks/feedback.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
defmodule Atlas.Feedbacks.Feedback do
@moduledoc """
The Feedback schema.
"""

use Ecto.Schema
import Ecto.Changeset

@required_fields ~w(subject message user_id)a
@primary_key {:id, :binary_id, autogenerate: true}
@foreign_key_type :binary_id
schema "feedbacks" do
field :message, :string
field :subject, :string
field :user_id, :binary_id

timestamps(type: :utc_datetime)
end

@doc false
def changeset(feedback, attrs) do
feedback
|> cast(attrs, @required_fields)
|> validate_required(@required_fields)
end
end
27 changes: 27 additions & 0 deletions lib/atlas_web/controllers/feedbacks/feedback_json.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule AtlasWeb.FeedbacksJSON do
alias Atlas.Feedbacks.Feedback

@doc """
Renders a list of feedbacks.
"""
def index(%{feedbacks: feedbacks}) do
%{data: for(feedback <- feedbacks, do: data(feedback))}
end

@doc """
Renders a single feedback.
"""
def show(%{feedback: feedback}) do
%{data: data(feedback)}
end

defp data(%Feedback{} = feedback) do
%{
id: feedback.id,
subject: feedback.subject,
message: feedback.message,
user_id: feedback.user_id,
inserted_at: feedback.inserted_at
}
end
end
64 changes: 64 additions & 0 deletions lib/atlas_web/controllers/feedbacks/feedbacks_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
defmodule AtlasWeb.FeedbacksController do
use AtlasWeb, :controller

alias Atlas.Feedbacks
alias Atlas.Feedbacks.Feedback

action_fallback AtlasWeb.FallbackController

def index(conn, _attrs) do
{user, _session} = Guardian.Plug.current_resource(conn)

feedbacks =
if user_has_elevated_privileges?(user) do
Feedbacks.list_feedbacks()
else
Feedbacks.list_feedbacks(where: [user_id: user.id])
end

render(conn, :index, feedbacks: feedbacks)
end

def create(conn, attrs) do
{user, _session} = Guardian.Plug.current_resource(conn)
attrs = Map.put(attrs, "user_id", user.id)

case Feedbacks.create_feedback(attrs) do
{:ok, feedback} ->
conn
|> put_status(:created)
|> render(:show, feedback: feedback)

{:error, _changeset} ->
conn
|> put_status(:unprocessable_entity)
|> json(%{errors: "Invalid fields"})
end
end

def delete(conn, %{"id" => id}) do
{user, _session} = Guardian.Plug.current_resource(conn)

if user_has_elevated_privileges?(user) do
case Feedbacks.get_feedback!(id) do
nil ->
conn
|> put_status(:not_found)
|> json(%{error: "Feedback not found"})

feedback ->
with {:ok, %Feedback{}} <- Feedbacks.delete_feedback(feedback) do
send_resp(conn, :no_content, "")
end
end
else
conn
|> put_status(:unauthorized)
|> json(%{error: "Unauthorized"})
end
end

defp user_has_elevated_privileges?(user) do
(user && user.type == :admin) || user.type == :professor
end
end
2 changes: 2 additions & 0 deletions lib/atlas_web/router.ex
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ defmodule AtlasWeb.Router do
resources "/", ShiftExchangeRequestController, only: [:index, :create, :show, :delete]
end

resources "/feedbacks", FeedbacksController, except: [:new, :edit, :show]

pipe_through :is_at_least_professor

get "/students", University.StudentsController, :index
Expand Down
16 changes: 16 additions & 0 deletions priv/repo/migrations/20250928211951_create_feedbacks.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule Atlas.Repo.Migrations.CreateFeedbacks do
use Ecto.Migration

def change do
create table(:feedbacks, primary_key: false) do
add :id, :binary_id, primary_key: true
add :subject, :string
add :message, :string
add :user_id, references(:users, on_delete: :nothing, type: :binary_id)

timestamps(type: :utc_datetime)
end

create index(:feedbacks, [:user_id])
end
end
3 changes: 2 additions & 1 deletion test/atlas/degrees_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ defmodule Atlas.DegreesTest do

test "list_degrees/0 returns all degrees" do
degree = degree_fixture()
assert Degrees.list_degrees() == [degree]
degrees = Degrees.list_degrees()
assert degree in degrees
end

test "get_degree!/1 returns the degree with given id" do
Expand Down