defmodule GitGud.Issues.Issue do
use Ecto.Schema
import Ecto.Changeset
alias GitGud.Accounts.User
alias GitGud.Issues.IssueComment
alias GitGud.Repositories.Repository
@valid_states ~w(open closed)
schema "issues" do
field :number, :integer
field :title, :string
field :body, :string
field :state, :string, default: "open"
field :closed_at, :utc_datetime
field :moderated_at, :utc_datetime
field :moderation_note, :string
field :original_body, :string
belongs_to :repository, Repository
belongs_to :author, User
belongs_to :moderated_by, User
has_many :comments, IssueComment
timestamps(type: :utc_datetime)
end
@doc """
Creation changeset. `repository_id`, `author_id`, and `number` are set by
the context — never via user input.
"""
def create_changeset(issue, attrs) do
issue
|> cast(attrs, [:title, :body])
|> validate_required([:title])
|> validate_length(:title, min: 1, max: 255)
|> validate_length(:body, max: 65_535)
end
def update_changeset(issue, attrs) do
issue
|> cast(attrs, [:title, :body])
|> validate_required([:title])
|> validate_length(:title, min: 1, max: 255)
|> validate_length(:body, max: 65_535)
end
def state_changeset(issue, state) when state in @valid_states do
change(issue, %{
state: state,
closed_at: if(state == "closed", do: DateTime.utc_now(:second))
})
end
def valid_states, do: @valid_states
@doc "Replace the body with a moderator note, preserving the original."
def moderate_changeset(target, moderator, note) do
original = target.original_body || target.body
change(target, %{
original_body: original,
body: "",
moderation_note: note,
moderated_by_id: moderator.id,
moderated_at: DateTime.utc_now(:second)
})
end
@doc "Reverse a previous moderation: restore the original body."
def restore_changeset(target) do
change(target, %{
body: target.original_body || target.body,
original_body: nil,
moderation_note: nil,
moderated_by_id: nil,
moderated_at: nil
})
end
def moderated?(%__MODULE__{moderated_at: nil}), do: false
def moderated?(%__MODULE__{}), do: true
end
2.2 KiB · text
5af55d9