Refactoring of Events context
This commit is contained in:
parent
e4a446003d
commit
e358dcce77
@ -1,33 +1,40 @@
|
|||||||
import EctoEnum
|
|
||||||
|
|
||||||
defenum(Mobilizon.Events.CommentVisibilityEnum, :comment_visibility_type, [
|
|
||||||
:public,
|
|
||||||
:unlisted,
|
|
||||||
:private,
|
|
||||||
:moderated,
|
|
||||||
:invite
|
|
||||||
])
|
|
||||||
|
|
||||||
defmodule Mobilizon.Events.Comment do
|
defmodule Mobilizon.Events.Comment do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
An actor comment (for instance on an event or on a group)
|
Represents an actor comment (for instance on an event or on a group).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
alias Mobilizon.Events.Event
|
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Events.Comment
|
alias Mobilizon.Config
|
||||||
alias MobilizonWeb.Router.Helpers, as: Routes
|
alias Mobilizon.Events.{Comment, CommentVisibility, Event}
|
||||||
alias MobilizonWeb.Endpoint
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
text: String.t(),
|
||||||
|
url: String.t(),
|
||||||
|
local: boolean,
|
||||||
|
visibility: CommentVisibility.t(),
|
||||||
|
uuid: Ecto.UUID.t(),
|
||||||
|
actor: Actor.t(),
|
||||||
|
attributed_to: Actor.t(),
|
||||||
|
event: Event.t(),
|
||||||
|
in_reply_to_comment: t,
|
||||||
|
origin_comment: t
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:text, :actor_id, :url]
|
||||||
|
@optional_attrs [:event_id, :in_reply_to_comment_id, :origin_comment_id, :attributed_to_id]
|
||||||
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
schema "comments" do
|
schema "comments" do
|
||||||
field(:text, :string)
|
field(:text, :string)
|
||||||
field(:url, :string)
|
field(:url, :string)
|
||||||
field(:local, :boolean, default: true)
|
field(:local, :boolean, default: true)
|
||||||
field(:visibility, Mobilizon.Events.CommentVisibilityEnum, default: :public)
|
field(:visibility, CommentVisibility, default: :public)
|
||||||
field(:uuid, Ecto.UUID)
|
field(:uuid, Ecto.UUID)
|
||||||
|
|
||||||
belongs_to(:actor, Actor, foreign_key: :actor_id)
|
belongs_to(:actor, Actor, foreign_key: :actor_id)
|
||||||
belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
|
belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
|
||||||
belongs_to(:event, Event, foreign_key: :event_id)
|
belongs_to(:event, Event, foreign_key: :event_id)
|
||||||
@ -37,38 +44,27 @@ defmodule Mobilizon.Events.Comment do
|
|||||||
timestamps(type: :utc_datetime)
|
timestamps(type: :utc_datetime)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
|
||||||
def changeset(comment, attrs) do
|
|
||||||
uuid =
|
|
||||||
if Map.has_key?(attrs, "uuid"),
|
|
||||||
do: attrs["uuid"],
|
|
||||||
else: Ecto.UUID.generate()
|
|
||||||
|
|
||||||
# TODO : really change me right away
|
|
||||||
url =
|
|
||||||
if Map.has_key?(attrs, "url"),
|
|
||||||
do: attrs["url"],
|
|
||||||
else: Routes.page_url(Endpoint, :comment, uuid)
|
|
||||||
|
|
||||||
comment
|
|
||||||
|> Ecto.Changeset.cast(attrs, [
|
|
||||||
:url,
|
|
||||||
:text,
|
|
||||||
:actor_id,
|
|
||||||
:event_id,
|
|
||||||
:in_reply_to_comment_id,
|
|
||||||
:origin_comment_id,
|
|
||||||
:attributed_to_id
|
|
||||||
])
|
|
||||||
|> put_change(:uuid, uuid)
|
|
||||||
|> put_change(:url, url)
|
|
||||||
|> validate_required([:text, :actor_id, :url])
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Returns the id of the first comment in the conversation
|
Returns the id of the first comment in the conversation.
|
||||||
"""
|
"""
|
||||||
|
@spec get_thread_id(t) :: integer
|
||||||
def get_thread_id(%Comment{id: id, origin_comment_id: origin_comment_id}) do
|
def get_thread_id(%Comment{id: id, origin_comment_id: origin_comment_id}) do
|
||||||
origin_comment_id || id
|
origin_comment_id || id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
|
def changeset(%Comment{} = comment, attrs) do
|
||||||
|
uuid = attrs["uuid"] || Ecto.UUID.generate()
|
||||||
|
url = attrs["url"] || generate_url(uuid)
|
||||||
|
|
||||||
|
comment
|
||||||
|
|> cast(attrs, @attrs)
|
||||||
|
|> put_change(:uuid, uuid)
|
||||||
|
|> put_change(:url, url)
|
||||||
|
|> validate_required(@required_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec generate_url(String.t()) :: String.t()
|
||||||
|
defp generate_url(uuid), do: "#{Config.instance_hostname()}/comments/#{uuid}"
|
||||||
end
|
end
|
||||||
|
@ -1,43 +1,88 @@
|
|||||||
import EctoEnum
|
|
||||||
|
|
||||||
defenum(Mobilizon.Events.EventVisibilityEnum, :event_visibility_type, [
|
|
||||||
:public,
|
|
||||||
:unlisted,
|
|
||||||
:restricted,
|
|
||||||
:private
|
|
||||||
])
|
|
||||||
|
|
||||||
defenum(Mobilizon.Events.JoinOptionsEnum, :event_join_options_type, [
|
|
||||||
:free,
|
|
||||||
:restricted,
|
|
||||||
:invite
|
|
||||||
])
|
|
||||||
|
|
||||||
defenum(Mobilizon.Events.EventStatusEnum, :event_status_type, [
|
|
||||||
:tentative,
|
|
||||||
:confirmed,
|
|
||||||
:cancelled
|
|
||||||
])
|
|
||||||
|
|
||||||
defenum(Mobilizon.Event.EventCategoryEnum, :event_category_type, [
|
|
||||||
:business,
|
|
||||||
:conference,
|
|
||||||
:birthday,
|
|
||||||
:demonstration,
|
|
||||||
:meeting
|
|
||||||
])
|
|
||||||
|
|
||||||
defmodule Mobilizon.Events.Event do
|
defmodule Mobilizon.Events.Event do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents an event
|
Represents an event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
alias Mobilizon.Events.{Event, Participant, Tag, Session, Track}
|
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
alias Mobilizon.Media.Picture
|
|
||||||
alias Mobilizon.Addresses.Address
|
alias Mobilizon.Addresses.Address
|
||||||
|
|
||||||
|
alias Mobilizon.Events.{
|
||||||
|
Event,
|
||||||
|
EventOptions,
|
||||||
|
EventStatus,
|
||||||
|
EventVisibility,
|
||||||
|
JoinOptions,
|
||||||
|
Participant,
|
||||||
|
Tag,
|
||||||
|
Session,
|
||||||
|
Track
|
||||||
|
}
|
||||||
|
|
||||||
|
alias Mobilizon.Media.Picture
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
url: String.t(),
|
||||||
|
local: boolean,
|
||||||
|
begins_on: DateTime.t(),
|
||||||
|
slug: String.t(),
|
||||||
|
description: String.t(),
|
||||||
|
ends_on: DateTime.t(),
|
||||||
|
title: String.t(),
|
||||||
|
status: EventStatus.t(),
|
||||||
|
visibility: EventVisibility.t(),
|
||||||
|
join_options: JoinOptions.t(),
|
||||||
|
publish_at: DateTime.t(),
|
||||||
|
uuid: Ecto.UUID.t(),
|
||||||
|
online_address: String.t(),
|
||||||
|
phone_address: String.t(),
|
||||||
|
category: String.t(),
|
||||||
|
options: EventOptions.t(),
|
||||||
|
organizer_actor: Actor.t(),
|
||||||
|
attributed_to: Actor.t(),
|
||||||
|
physical_address: Address.t(),
|
||||||
|
picture: Picture.t(),
|
||||||
|
tracks: [Track.t()],
|
||||||
|
sessions: [Session.t()],
|
||||||
|
tags: [Tag.t()],
|
||||||
|
participants: [Actor.t()]
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:title, :begins_on, :organizer_actor_id, :url, :uuid]
|
||||||
|
@optional_attrs [
|
||||||
|
:slug,
|
||||||
|
:description,
|
||||||
|
:ends_on,
|
||||||
|
:category,
|
||||||
|
:status,
|
||||||
|
:visibility,
|
||||||
|
:publish_at,
|
||||||
|
:online_address,
|
||||||
|
:phone_address,
|
||||||
|
:picture_id,
|
||||||
|
:physical_address_id
|
||||||
|
]
|
||||||
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
|
@update_required_attrs @required_attrs
|
||||||
|
@update_optional_attrs [
|
||||||
|
:slug,
|
||||||
|
:description,
|
||||||
|
:ends_on,
|
||||||
|
:category,
|
||||||
|
:status,
|
||||||
|
:visibility,
|
||||||
|
:publish_at,
|
||||||
|
:online_address,
|
||||||
|
:phone_address,
|
||||||
|
:picture_id,
|
||||||
|
:physical_address_id
|
||||||
|
]
|
||||||
|
@update_attrs @update_required_attrs ++ @update_optional_attrs
|
||||||
|
|
||||||
schema "events" do
|
schema "events" do
|
||||||
field(:url, :string)
|
field(:url, :string)
|
||||||
field(:local, :boolean, default: true)
|
field(:local, :boolean, default: true)
|
||||||
@ -46,96 +91,59 @@ defmodule Mobilizon.Events.Event do
|
|||||||
field(:description, :string)
|
field(:description, :string)
|
||||||
field(:ends_on, :utc_datetime)
|
field(:ends_on, :utc_datetime)
|
||||||
field(:title, :string)
|
field(:title, :string)
|
||||||
field(:status, Mobilizon.Events.EventStatusEnum, default: :confirmed)
|
field(:status, EventStatus, default: :confirmed)
|
||||||
field(:visibility, Mobilizon.Events.EventVisibilityEnum, default: :public)
|
field(:visibility, EventVisibility, default: :public)
|
||||||
field(:join_options, Mobilizon.Events.JoinOptionsEnum, default: :free)
|
field(:join_options, JoinOptions, default: :free)
|
||||||
field(:publish_at, :utc_datetime)
|
field(:publish_at, :utc_datetime)
|
||||||
field(:uuid, Ecto.UUID, default: Ecto.UUID.generate())
|
field(:uuid, Ecto.UUID, default: Ecto.UUID.generate())
|
||||||
field(:online_address, :string)
|
field(:online_address, :string)
|
||||||
field(:phone_address, :string)
|
field(:phone_address, :string)
|
||||||
field(:category, :string)
|
field(:category, :string)
|
||||||
embeds_one(:options, Mobilizon.Events.EventOptions, on_replace: :update)
|
|
||||||
|
embeds_one(:options, EventOptions, on_replace: :update)
|
||||||
belongs_to(:organizer_actor, Actor, foreign_key: :organizer_actor_id)
|
belongs_to(:organizer_actor, Actor, foreign_key: :organizer_actor_id)
|
||||||
belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
|
belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
|
||||||
many_to_many(:tags, Tag, join_through: "events_tags", on_replace: :delete)
|
|
||||||
many_to_many(:participants, Actor, join_through: Participant)
|
|
||||||
has_many(:tracks, Track)
|
|
||||||
has_many(:sessions, Session)
|
|
||||||
belongs_to(:physical_address, Address)
|
belongs_to(:physical_address, Address)
|
||||||
belongs_to(:picture, Picture)
|
belongs_to(:picture, Picture)
|
||||||
|
has_many(:tracks, Track)
|
||||||
|
has_many(:sessions, Session)
|
||||||
|
many_to_many(:tags, Tag, join_through: "events_tags", on_replace: :delete)
|
||||||
|
many_to_many(:participants, Actor, join_through: Participant)
|
||||||
|
|
||||||
timestamps(type: :utc_datetime)
|
timestamps(type: :utc_datetime)
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%Event{} = event, attrs) do
|
def changeset(%Event{} = event, attrs) do
|
||||||
event
|
event
|
||||||
|> Ecto.Changeset.cast(attrs, [
|
|> cast(attrs, @attrs)
|
||||||
:title,
|
|
||||||
:slug,
|
|
||||||
:description,
|
|
||||||
:url,
|
|
||||||
:begins_on,
|
|
||||||
:ends_on,
|
|
||||||
:organizer_actor_id,
|
|
||||||
:category,
|
|
||||||
:status,
|
|
||||||
:visibility,
|
|
||||||
:publish_at,
|
|
||||||
:online_address,
|
|
||||||
:phone_address,
|
|
||||||
:uuid,
|
|
||||||
:picture_id,
|
|
||||||
:physical_address_id
|
|
||||||
])
|
|
||||||
|> cast_embed(:options)
|
|> cast_embed(:options)
|
||||||
|> validate_required([
|
|> validate_required(@required_attrs)
|
||||||
:title,
|
|
||||||
:begins_on,
|
|
||||||
:organizer_actor_id,
|
|
||||||
:url,
|
|
||||||
:uuid
|
|
||||||
])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec update_changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def update_changeset(%Event{} = event, attrs) do
|
def update_changeset(%Event{} = event, attrs) do
|
||||||
event
|
event
|
||||||
|> Ecto.Changeset.cast(attrs, [
|
|> Ecto.Changeset.cast(attrs, @update_attrs)
|
||||||
:title,
|
|
||||||
:slug,
|
|
||||||
:description,
|
|
||||||
:begins_on,
|
|
||||||
:ends_on,
|
|
||||||
:category,
|
|
||||||
:status,
|
|
||||||
:visibility,
|
|
||||||
:publish_at,
|
|
||||||
:online_address,
|
|
||||||
:phone_address,
|
|
||||||
:picture_id,
|
|
||||||
:physical_address_id
|
|
||||||
])
|
|
||||||
|> cast_embed(:options)
|
|> cast_embed(:options)
|
||||||
|> put_tags(attrs)
|
|> put_tags(attrs)
|
||||||
|> validate_required([
|
|> validate_required(@update_required_attrs)
|
||||||
:title,
|
|
||||||
:begins_on,
|
|
||||||
:organizer_actor_id,
|
|
||||||
:url,
|
|
||||||
:uuid
|
|
||||||
])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
defp put_tags(changeset, %{"tags" => tags}), do: put_assoc(changeset, :tags, tags)
|
@doc """
|
||||||
defp put_tags(changeset, _), do: changeset
|
Checks whether an event can be managed.
|
||||||
|
"""
|
||||||
def can_event_be_managed_by(%Event{organizer_actor_id: organizer_actor_id}, actor_id)
|
@spec can_be_managed_by(t, integer | String.t()) :: boolean
|
||||||
|
def can_be_managed_by(%Event{organizer_actor_id: organizer_actor_id}, actor_id)
|
||||||
when organizer_actor_id == actor_id do
|
when organizer_actor_id == actor_id do
|
||||||
{:event_can_be_managed, true}
|
{:event_can_be_managed, true}
|
||||||
end
|
end
|
||||||
|
|
||||||
def can_event_be_managed_by(_event, _actor) do
|
def can_be_managed_by(_event, _actor), do: {:event_can_be_managed, false}
|
||||||
{:event_can_be_managed, false}
|
|
||||||
end
|
@spec put_tags(Ecto.Changeset.t(), map) :: Ecto.Changeset.t()
|
||||||
|
defp put_tags(changeset, %{"tags" => tags}), do: put_assoc(changeset, :tags, tags)
|
||||||
|
defp put_tags(changeset, _), do: changeset
|
||||||
end
|
end
|
||||||
|
19
lib/mobilizon/events/event_offer.ex
Normal file
19
lib/mobilizon/events/event_offer.ex
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
defmodule Mobilizon.Events.EventOffer do
|
||||||
|
@moduledoc """
|
||||||
|
Represents an event offer.
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
price: float,
|
||||||
|
price_currency: String.t(),
|
||||||
|
url: String.t()
|
||||||
|
}
|
||||||
|
|
||||||
|
embedded_schema do
|
||||||
|
field(:price, :float)
|
||||||
|
field(:price_currency, :string)
|
||||||
|
field(:url, :string)
|
||||||
|
end
|
||||||
|
end
|
@ -1,69 +1,58 @@
|
|||||||
import EctoEnum
|
|
||||||
|
|
||||||
defenum(Mobilizon.Events.CommentModeration, :comment_moderation, [:allow_all, :moderated, :closed])
|
|
||||||
|
|
||||||
defmodule Mobilizon.Events.EventOffer do
|
|
||||||
@moduledoc """
|
|
||||||
Represents an event offer
|
|
||||||
"""
|
|
||||||
use Ecto.Schema
|
|
||||||
|
|
||||||
embedded_schema do
|
|
||||||
field(:price, :float)
|
|
||||||
field(:price_currency, :string)
|
|
||||||
field(:url, :string)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defmodule Mobilizon.Events.EventParticipationCondition do
|
|
||||||
@moduledoc """
|
|
||||||
Represents an event participation condition
|
|
||||||
"""
|
|
||||||
use Ecto.Schema
|
|
||||||
|
|
||||||
embedded_schema do
|
|
||||||
field(:title, :string)
|
|
||||||
field(:content, :string)
|
|
||||||
field(:url, :string)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
defmodule Mobilizon.Events.EventOptions do
|
defmodule Mobilizon.Events.EventOptions do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents an event options
|
Represents an event options.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
|
import Ecto.Changeset
|
||||||
|
|
||||||
alias Mobilizon.Events.{
|
alias Mobilizon.Events.{
|
||||||
EventOptions,
|
|
||||||
EventOffer,
|
EventOffer,
|
||||||
|
EventOptions,
|
||||||
EventParticipationCondition,
|
EventParticipationCondition,
|
||||||
CommentModeration
|
CommentModeration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
maximum_attendee_capacity: integer,
|
||||||
|
remaining_attendee_capacity: integer,
|
||||||
|
show_remaining_attendee_capacity: boolean,
|
||||||
|
attendees: [String.t()],
|
||||||
|
program: String.t(),
|
||||||
|
comment_moderation: CommentModeration.t(),
|
||||||
|
show_participation_price: boolean,
|
||||||
|
offers: [EventOffer.t()],
|
||||||
|
participation_condition: [EventParticipationCondition.t()]
|
||||||
|
}
|
||||||
|
|
||||||
|
@attrs [
|
||||||
|
:maximum_attendee_capacity,
|
||||||
|
:remaining_attendee_capacity,
|
||||||
|
:show_remaining_attendee_capacity,
|
||||||
|
:attendees,
|
||||||
|
:program,
|
||||||
|
:comment_moderation,
|
||||||
|
:show_participation_price
|
||||||
|
]
|
||||||
|
|
||||||
@primary_key false
|
@primary_key false
|
||||||
embedded_schema do
|
embedded_schema do
|
||||||
field(:maximum_attendee_capacity, :integer)
|
field(:maximum_attendee_capacity, :integer)
|
||||||
field(:remaining_attendee_capacity, :integer)
|
field(:remaining_attendee_capacity, :integer)
|
||||||
field(:show_remaining_attendee_capacity, :boolean)
|
field(:show_remaining_attendee_capacity, :boolean)
|
||||||
embeds_many(:offers, EventOffer)
|
|
||||||
embeds_many(:participation_condition, EventParticipationCondition)
|
|
||||||
field(:attendees, {:array, :string})
|
field(:attendees, {:array, :string})
|
||||||
field(:program, :string)
|
field(:program, :string)
|
||||||
field(:comment_moderation, CommentModeration)
|
field(:comment_moderation, CommentModeration)
|
||||||
field(:show_participation_price, :boolean)
|
field(:show_participation_price, :boolean)
|
||||||
|
|
||||||
|
embeds_many(:offers, EventOffer)
|
||||||
|
embeds_many(:participation_condition, EventParticipationCondition)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%EventOptions{} = event_options, attrs) do
|
def changeset(%EventOptions{} = event_options, attrs) do
|
||||||
event_options
|
cast(event_options, attrs, @attrs)
|
||||||
|> Ecto.Changeset.cast(attrs, [
|
|
||||||
:maximum_attendee_capacity,
|
|
||||||
:remaining_attendee_capacity,
|
|
||||||
:show_remaining_attendee_capacity,
|
|
||||||
:attendees,
|
|
||||||
:program,
|
|
||||||
:comment_moderation,
|
|
||||||
:show_participation_price
|
|
||||||
])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
19
lib/mobilizon/events/event_participation_condition.ex
Normal file
19
lib/mobilizon/events/event_participation_condition.ex
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
defmodule Mobilizon.Events.EventParticipationCondition do
|
||||||
|
@moduledoc """
|
||||||
|
Represents an event participation condition.
|
||||||
|
"""
|
||||||
|
|
||||||
|
use Ecto.Schema
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
title: String.t(),
|
||||||
|
content: String.t(),
|
||||||
|
url: String.t()
|
||||||
|
}
|
||||||
|
|
||||||
|
embedded_schema do
|
||||||
|
field(:title, :string)
|
||||||
|
field(:content, :string)
|
||||||
|
field(:url, :string)
|
||||||
|
end
|
||||||
|
end
|
@ -4,6 +4,7 @@ defmodule Mobilizon.Events do
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
import Ecto.Query
|
import Ecto.Query
|
||||||
|
import EctoEnum
|
||||||
|
|
||||||
import Mobilizon.Storage.Ecto
|
import Mobilizon.Storage.Ecto
|
||||||
|
|
||||||
@ -13,13 +14,62 @@ defmodule Mobilizon.Events do
|
|||||||
alias Mobilizon.Storage.{Page, Repo}
|
alias Mobilizon.Storage.{Page, Repo}
|
||||||
alias Mobilizon.Users.User
|
alias Mobilizon.Users.User
|
||||||
|
|
||||||
def data() do
|
defenum(EventVisibility, :event_visibility, [
|
||||||
Dataloader.Ecto.new(Repo, query: &query/2)
|
:public,
|
||||||
end
|
:unlisted,
|
||||||
|
:restricted,
|
||||||
|
:private
|
||||||
|
])
|
||||||
|
|
||||||
def query(queryable, _params) do
|
defenum(JoinOptions, :join_options, [
|
||||||
queryable
|
:free,
|
||||||
end
|
:restricted,
|
||||||
|
:invite
|
||||||
|
])
|
||||||
|
|
||||||
|
defenum(EventStatus, :event_status, [
|
||||||
|
:tentative,
|
||||||
|
:confirmed,
|
||||||
|
:cancelled
|
||||||
|
])
|
||||||
|
|
||||||
|
defenum(EventCategory, :event_category, [
|
||||||
|
:business,
|
||||||
|
:conference,
|
||||||
|
:birthday,
|
||||||
|
:demonstration,
|
||||||
|
:meeting
|
||||||
|
])
|
||||||
|
|
||||||
|
defenum(CommentVisibility, :comment_visibility, [
|
||||||
|
:public,
|
||||||
|
:unlisted,
|
||||||
|
:private,
|
||||||
|
:moderated,
|
||||||
|
:invite
|
||||||
|
])
|
||||||
|
|
||||||
|
defenum(CommentModeration, :comment_moderation, [
|
||||||
|
:allow_all,
|
||||||
|
:moderated,
|
||||||
|
:closed
|
||||||
|
])
|
||||||
|
|
||||||
|
defenum(ParticipantRole, :participant_role, [
|
||||||
|
:not_approved,
|
||||||
|
:participant,
|
||||||
|
:moderator,
|
||||||
|
:administrator,
|
||||||
|
:creator
|
||||||
|
])
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
@spec data :: Dataloader.Ecto.t()
|
||||||
|
def data, do: Dataloader.Ecto.new(Repo, query: &query/2)
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
@spec query(Ecto.Query.t(), map) :: Ecto.Query.t()
|
||||||
|
def query(queryable, _params), do: queryable
|
||||||
|
|
||||||
def get_public_events_for_actor(%Actor{id: actor_id} = _actor, page \\ nil, limit \\ nil) do
|
def get_public_events_for_actor(%Actor{id: actor_id} = _actor, page \\ nil, limit \\ nil) do
|
||||||
query =
|
query =
|
||||||
@ -537,6 +587,18 @@ defmodule Mobilizon.Events do
|
|||||||
|
|
||||||
def get_tag(id), do: Repo.get(Tag, id)
|
def get_tag(id), do: Repo.get(Tag, id)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_tag_by_slug(slug) do
|
||||||
|
query =
|
||||||
|
from(
|
||||||
|
t in Tag,
|
||||||
|
where: t.slug == ^slug
|
||||||
|
)
|
||||||
|
|
||||||
|
Repo.one(query)
|
||||||
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
Get an existing tag or create one
|
Get an existing tag or create one
|
||||||
"""
|
"""
|
||||||
@ -698,6 +760,9 @@ defmodule Mobilizon.Events do
|
|||||||
Repo.all(final_query)
|
Repo.all(final_query)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
alias Mobilizon.Events.Participant
|
alias Mobilizon.Events.Participant
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
|
@ -1,16 +1,30 @@
|
|||||||
defmodule Mobilizon.Events.FeedToken do
|
defmodule Mobilizon.Events.FeedToken do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents a Token for a Feed of events
|
Represents a token for a feed of events.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
alias Mobilizon.Events.FeedToken
|
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
|
alias Mobilizon.Events.FeedToken
|
||||||
alias Mobilizon.Users.User
|
alias Mobilizon.Users.User
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
token: Ecto.UUID.t(),
|
||||||
|
actor: Actor.t(),
|
||||||
|
user: User.t()
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:token, :user_id]
|
||||||
|
@optional_attrs [:actor_id]
|
||||||
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
@primary_key false
|
@primary_key false
|
||||||
schema "feed_tokens" do
|
schema "feed_tokens" do
|
||||||
field(:token, Ecto.UUID, primary_key: true)
|
field(:token, Ecto.UUID, primary_key: true)
|
||||||
|
|
||||||
belongs_to(:actor, Actor)
|
belongs_to(:actor, Actor)
|
||||||
belongs_to(:user, User)
|
belongs_to(:user, User)
|
||||||
|
|
||||||
@ -18,9 +32,10 @@ defmodule Mobilizon.Events.FeedToken do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%FeedToken{} = feed_token, attrs) do
|
def changeset(%FeedToken{} = feed_token, attrs) do
|
||||||
feed_token
|
feed_token
|
||||||
|> Ecto.Changeset.cast(attrs, [:token, :actor_id, :user_id])
|
|> cast(attrs, @attrs)
|
||||||
|> validate_required([:token, :user_id])
|
|> validate_required(@required_attrs)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,73 +1,46 @@
|
|||||||
import EctoEnum
|
|
||||||
|
|
||||||
defenum(Mobilizon.Events.ParticipantRoleEnum, :participant_role_type, [
|
|
||||||
:not_approved,
|
|
||||||
:participant,
|
|
||||||
:moderator,
|
|
||||||
:administrator,
|
|
||||||
:creator
|
|
||||||
])
|
|
||||||
|
|
||||||
defmodule Mobilizon.Events.Participant do
|
defmodule Mobilizon.Events.Participant do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents a participant, an actor participating to an event
|
Represents a participant, an actor participating to an event.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
alias Mobilizon.Events.{Participant, Event}
|
|
||||||
alias Mobilizon.Actors.Actor
|
alias Mobilizon.Actors.Actor
|
||||||
|
alias Mobilizon.Config
|
||||||
|
alias Mobilizon.Events
|
||||||
|
alias Mobilizon.Events.{Event, Participant, ParticipantRole}
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
role: ParticipantRole.t(),
|
||||||
|
url: String.t(),
|
||||||
|
event: Event.t(),
|
||||||
|
actor: Actor.t()
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:url, :role, :event_id, :actor_id]
|
||||||
|
@attrs @required_attrs
|
||||||
|
|
||||||
@primary_key {:id, :binary_id, autogenerate: true}
|
@primary_key {:id, :binary_id, autogenerate: true}
|
||||||
schema "participants" do
|
schema "participants" do
|
||||||
field(:role, Mobilizon.Events.ParticipantRoleEnum, default: :participant)
|
field(:role, ParticipantRole, default: :participant)
|
||||||
field(:url, :string)
|
field(:url, :string)
|
||||||
|
|
||||||
belongs_to(:event, Event, primary_key: true)
|
belongs_to(:event, Event, primary_key: true)
|
||||||
belongs_to(:actor, Actor, primary_key: true)
|
belongs_to(:actor, Actor, primary_key: true)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
|
||||||
def changeset(%Participant{} = participant, attrs) do
|
|
||||||
participant
|
|
||||||
|> Ecto.Changeset.cast(attrs, [:url, :role, :event_id, :actor_id])
|
|
||||||
|> generate_url()
|
|
||||||
|> validate_required([:url, :role, :event_id, :actor_id])
|
|
||||||
end
|
|
||||||
|
|
||||||
# If there's a blank URL that's because we're doing the first insert
|
|
||||||
defp generate_url(%Ecto.Changeset{data: %Participant{url: nil}} = changeset) do
|
|
||||||
case fetch_change(changeset, :url) do
|
|
||||||
{:ok, _url} -> changeset
|
|
||||||
:error -> do_generate_url(changeset)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Most time just go with the given URL
|
|
||||||
defp generate_url(%Ecto.Changeset{} = changeset), do: changeset
|
|
||||||
|
|
||||||
defp do_generate_url(%Ecto.Changeset{} = changeset) do
|
|
||||||
uuid = Ecto.UUID.generate()
|
|
||||||
|
|
||||||
changeset
|
|
||||||
|> put_change(
|
|
||||||
:url,
|
|
||||||
"#{MobilizonWeb.Endpoint.url()}/join/event/#{uuid}"
|
|
||||||
)
|
|
||||||
|> put_change(
|
|
||||||
:id,
|
|
||||||
uuid
|
|
||||||
)
|
|
||||||
end
|
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
We check that the actor asking to leave the event is not it's only organizer
|
We check that the actor asking to leave the event is not it's only organizer.
|
||||||
We start by fetching the list of organizers and if there's only one of them
|
We start by fetching the list of organizers and if there's only one of them
|
||||||
and that it's the actor requesting leaving the event we return true
|
and that it's the actor requesting leaving the event we return true.
|
||||||
"""
|
"""
|
||||||
@spec check_that_participant_is_not_only_organizer(integer(), integer()) :: boolean()
|
@spec is_not_only_organizer(integer | String.t(), integer | String.t()) :: boolean
|
||||||
def check_that_participant_is_not_only_organizer(event_id, actor_id) do
|
def is_not_only_organizer(event_id, actor_id) do
|
||||||
case Mobilizon.Events.list_organizers_participants_for_event(event_id) do
|
case Events.list_organizers_participants_for_event(event_id) do
|
||||||
[%Participant{actor: %Actor{id: participant_actor_id}}] ->
|
[%Participant{actor: %Actor{id: participant_actor_id}}] ->
|
||||||
participant_actor_id == actor_id
|
participant_actor_id == actor_id
|
||||||
|
|
||||||
@ -75,4 +48,39 @@ defmodule Mobilizon.Events.Participant do
|
|||||||
false
|
false
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
|
def changeset(%Participant{} = participant, attrs) do
|
||||||
|
participant
|
||||||
|
|> cast(attrs, @attrs)
|
||||||
|
|> ensure_url()
|
||||||
|
|> validate_required(@required_attrs)
|
||||||
|
end
|
||||||
|
|
||||||
|
# If there's a blank URL that's because we're doing the first insert
|
||||||
|
@spec ensure_url(Ecto.Changeset.t()) :: Ecto.Changeset.t()
|
||||||
|
defp ensure_url(%Ecto.Changeset{data: %Participant{url: nil}} = changeset) do
|
||||||
|
case fetch_change(changeset, :url) do
|
||||||
|
{:ok, _url} ->
|
||||||
|
changeset
|
||||||
|
|
||||||
|
:error ->
|
||||||
|
update_url(changeset)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
defp ensure_url(%Ecto.Changeset{} = changeset), do: changeset
|
||||||
|
|
||||||
|
defp update_url(%Ecto.Changeset{} = changeset) do
|
||||||
|
uuid = Ecto.UUID.generate()
|
||||||
|
url = generate_url(uuid)
|
||||||
|
|
||||||
|
changeset
|
||||||
|
|> put_change(:id, uuid)
|
||||||
|
|> put_change(:url, url)
|
||||||
|
end
|
||||||
|
|
||||||
|
@spec generate_url(String.t()) :: String.t()
|
||||||
|
defp generate_url(uuid), do: "#{Config.instance_hostname()}/join/event/#{uuid}"
|
||||||
end
|
end
|
||||||
|
@ -1,10 +1,41 @@
|
|||||||
defmodule Mobilizon.Events.Session do
|
defmodule Mobilizon.Events.Session do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents a session for an event (such as a talk at a conference)
|
Represents a session for an event (such as a talk at a conference).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
alias Mobilizon.Events.{Session, Event, Track}
|
|
||||||
|
alias Mobilizon.Events.{Event, Session, Track}
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
audios_urls: String.t(),
|
||||||
|
language: String.t(),
|
||||||
|
long_abstract: String.t(),
|
||||||
|
short_abstract: String.t(),
|
||||||
|
slides_url: String.t(),
|
||||||
|
subtitle: String.t(),
|
||||||
|
title: String.t(),
|
||||||
|
videos_urls: String.t(),
|
||||||
|
begins_on: DateTime.t(),
|
||||||
|
ends_on: DateTime.t(),
|
||||||
|
event: Event.t(),
|
||||||
|
track: Track.t()
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [
|
||||||
|
:title,
|
||||||
|
:subtitle,
|
||||||
|
:short_abstract,
|
||||||
|
:long_abstract,
|
||||||
|
:language,
|
||||||
|
:slides_url,
|
||||||
|
:videos_urls,
|
||||||
|
:audios_urls
|
||||||
|
]
|
||||||
|
@optional_attrs [:event_id, :track_id]
|
||||||
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
schema "sessions" do
|
schema "sessions" do
|
||||||
field(:audios_urls, :string)
|
field(:audios_urls, :string)
|
||||||
@ -17,6 +48,7 @@ defmodule Mobilizon.Events.Session do
|
|||||||
field(:videos_urls, :string)
|
field(:videos_urls, :string)
|
||||||
field(:begins_on, :utc_datetime)
|
field(:begins_on, :utc_datetime)
|
||||||
field(:ends_on, :utc_datetime)
|
field(:ends_on, :utc_datetime)
|
||||||
|
|
||||||
belongs_to(:event, Event)
|
belongs_to(:event, Event)
|
||||||
belongs_to(:track, Track)
|
belongs_to(:track, Track)
|
||||||
|
|
||||||
@ -24,29 +56,10 @@ defmodule Mobilizon.Events.Session do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%Session{} = session, attrs) do
|
def changeset(%Session{} = session, attrs) do
|
||||||
session
|
session
|
||||||
|> cast(attrs, [
|
|> cast(attrs, @attrs)
|
||||||
:title,
|
|> validate_required(@required_attrs)
|
||||||
:subtitle,
|
|
||||||
:short_abstract,
|
|
||||||
:long_abstract,
|
|
||||||
:language,
|
|
||||||
:slides_url,
|
|
||||||
:videos_urls,
|
|
||||||
:audios_urls,
|
|
||||||
:event_id,
|
|
||||||
:track_id
|
|
||||||
])
|
|
||||||
|> validate_required([
|
|
||||||
:title,
|
|
||||||
:subtitle,
|
|
||||||
:short_abstract,
|
|
||||||
:long_abstract,
|
|
||||||
:language,
|
|
||||||
:slides_url,
|
|
||||||
:videos_urls,
|
|
||||||
:audios_urls
|
|
||||||
])
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,40 +1,40 @@
|
|||||||
defmodule Mobilizon.Events.Tag do
|
defmodule Mobilizon.Events.Tag do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents a tag for events
|
Represents a tag for events.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
alias Mobilizon.Events.Tag
|
|
||||||
|
alias Mobilizon.Events.{Tag, TagRelation}
|
||||||
alias Mobilizon.Events.Tag.TitleSlug
|
alias Mobilizon.Events.Tag.TitleSlug
|
||||||
alias Mobilizon.Events.TagRelation
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
title: String.t(),
|
||||||
|
slug: TitleSlug.Type.t(),
|
||||||
|
related_tags: [Tag.t()]
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:title, :slug]
|
||||||
|
@attrs @required_attrs
|
||||||
|
|
||||||
schema "tags" do
|
schema "tags" do
|
||||||
field(:title, :string)
|
field(:title, :string)
|
||||||
field(:slug, TitleSlug.Type)
|
field(:slug, TitleSlug.Type)
|
||||||
|
|
||||||
many_to_many(:related_tags, Tag, join_through: TagRelation)
|
many_to_many(:related_tags, Tag, join_through: TagRelation)
|
||||||
|
|
||||||
timestamps()
|
timestamps()
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%Tag{} = tag, attrs) do
|
def changeset(%Tag{} = tag, attrs) do
|
||||||
tag
|
tag
|
||||||
|> cast(attrs, [:title])
|
|> cast(attrs, @attrs)
|
||||||
|> TitleSlug.maybe_generate_slug()
|
|> TitleSlug.maybe_generate_slug()
|
||||||
|> validate_required([:title, :slug])
|
|> validate_required(@required_attrs)
|
||||||
|> TitleSlug.unique_constraint()
|
|> TitleSlug.unique_constraint()
|
||||||
end
|
end
|
||||||
|
|
||||||
def increment_slug(slug) do
|
|
||||||
case List.pop_at(String.split(slug, "-"), -1) do
|
|
||||||
{nil, _} ->
|
|
||||||
slug
|
|
||||||
|
|
||||||
{suffix, slug_parts} ->
|
|
||||||
case Integer.parse(suffix) do
|
|
||||||
{id, _} -> Enum.join(slug_parts, "-") <> "-" <> Integer.to_string(id + 1)
|
|
||||||
:error -> slug <> "-1"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -1,33 +1,53 @@
|
|||||||
defmodule Mobilizon.Events.Tag.TitleSlug do
|
defmodule Mobilizon.Events.Tag.TitleSlug do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Generates slugs for tags
|
Generates slugs for tags.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
alias Mobilizon.Events.Tag
|
|
||||||
import Ecto.Query
|
|
||||||
alias Mobilizon.Storage.Repo
|
|
||||||
use EctoAutoslugField.Slug, from: :title, to: :slug
|
use EctoAutoslugField.Slug, from: :title, to: :slug
|
||||||
|
|
||||||
|
alias Mobilizon.Events
|
||||||
|
|
||||||
|
@slug_separator "-"
|
||||||
|
|
||||||
|
@doc """
|
||||||
|
Builds a slug.
|
||||||
|
"""
|
||||||
|
@spec build_slug(keyword, Ecto.Changeset.t()) :: String.t()
|
||||||
def build_slug(sources, changeset) do
|
def build_slug(sources, changeset) do
|
||||||
slug = super(sources, changeset)
|
slug = super(sources, changeset)
|
||||||
|
|
||||||
build_unique_slug(slug, changeset)
|
build_unique_slug(slug, changeset)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec build_unique_slug(String.t(), Ecto.Changeset.t()) :: String.t()
|
||||||
defp build_unique_slug(slug, changeset) do
|
defp build_unique_slug(slug, changeset) do
|
||||||
query =
|
case Events.get_tag_by_slug(slug) do
|
||||||
from(
|
|
||||||
t in Tag,
|
|
||||||
where: t.slug == ^slug
|
|
||||||
)
|
|
||||||
|
|
||||||
case Repo.one(query) do
|
|
||||||
nil ->
|
nil ->
|
||||||
slug
|
slug
|
||||||
|
|
||||||
_tag ->
|
_tag ->
|
||||||
slug
|
slug
|
||||||
|> Tag.increment_slug()
|
|> increment_slug()
|
||||||
|> build_unique_slug(changeset)
|
|> build_unique_slug(changeset)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@spec increment_slug(String.t()) :: String.t()
|
||||||
|
defp increment_slug(slug) do
|
||||||
|
case List.pop_at(String.split(slug, @slug_separator), -1) do
|
||||||
|
{nil, _} ->
|
||||||
|
slug
|
||||||
|
|
||||||
|
{suffix, slug_parts} ->
|
||||||
|
case Integer.parse(suffix) do
|
||||||
|
{id, _} ->
|
||||||
|
Enum.join(slug_parts, @slug_separator) <>
|
||||||
|
@slug_separator <>
|
||||||
|
Integer.to_string(id + 1)
|
||||||
|
|
||||||
|
:error ->
|
||||||
|
"#{slug}#{@slug_separator}1"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,36 +1,43 @@
|
|||||||
defmodule Mobilizon.Events.TagRelation do
|
defmodule Mobilizon.Events.TagRelation do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents a tag for events
|
Represents a tag relation.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
alias Mobilizon.Events.Tag
|
|
||||||
alias Mobilizon.Events.TagRelation
|
alias Mobilizon.Events.{Tag, TagRelation}
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
weight: integer,
|
||||||
|
tag: Tag.t(),
|
||||||
|
link: Tag.t()
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:tag_id, :link_id]
|
||||||
|
@optional_attrs [:weight]
|
||||||
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
@primary_key false
|
@primary_key false
|
||||||
schema "tag_relations" do
|
schema "tag_relations" do
|
||||||
|
field(:weight, :integer, default: 1)
|
||||||
|
|
||||||
belongs_to(:tag, Tag, primary_key: true)
|
belongs_to(:tag, Tag, primary_key: true)
|
||||||
belongs_to(:link, Tag, primary_key: true)
|
belongs_to(:link, Tag, primary_key: true)
|
||||||
field(:weight, :integer, default: 1)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%TagRelation{} = tag, attrs) do
|
def changeset(%TagRelation{} = tag, attrs) do
|
||||||
changeset =
|
|
||||||
tag
|
|
||||||
|> cast(attrs, [:tag_id, :link_id, :weight])
|
|
||||||
|> validate_required([:tag_id, :link_id])
|
|
||||||
|
|
||||||
# Return if tag_id or link_id are not set because it will fail later otherwise
|
# Return if tag_id or link_id are not set because it will fail later otherwise
|
||||||
with %Ecto.Changeset{errors: []} <- changeset do
|
with %Ecto.Changeset{errors: [], changes: changes} = changeset <-
|
||||||
changes = changeset.changes
|
tag
|
||||||
|
|> cast(attrs, @attrs)
|
||||||
changeset =
|
|> validate_required(@required_attrs) do
|
||||||
changeset
|
|
||||||
|> put_change(:tag_id, min(changes.tag_id, changes.link_id))
|
|
||||||
|> put_change(:link_id, max(changes.tag_id, changes.link_id))
|
|
||||||
|
|
||||||
changeset
|
changeset
|
||||||
|
|> put_change(:tag_id, min(changes.tag_id, changes.link_id))
|
||||||
|
|> put_change(:link_id, max(changes.tag_id, changes.link_id))
|
||||||
|> unique_constraint(:tag_id, name: :tag_relations_pkey)
|
|> unique_constraint(:tag_id, name: :tag_relations_pkey)
|
||||||
|> check_constraint(:tag_id,
|
|> check_constraint(:tag_id,
|
||||||
name: :no_self_loops_check,
|
name: :no_self_loops_check,
|
||||||
|
@ -1,15 +1,31 @@
|
|||||||
defmodule Mobilizon.Events.Track do
|
defmodule Mobilizon.Events.Track do
|
||||||
@moduledoc """
|
@moduledoc """
|
||||||
Represents a track for an event (such as a theme) having multiple sessions
|
Represents a track for an event (such as a theme) having multiple sessions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
use Ecto.Schema
|
use Ecto.Schema
|
||||||
|
|
||||||
import Ecto.Changeset
|
import Ecto.Changeset
|
||||||
|
|
||||||
alias Mobilizon.Events.{Track, Event, Session}
|
alias Mobilizon.Events.{Track, Event, Session}
|
||||||
|
|
||||||
|
@type t :: %__MODULE__{
|
||||||
|
color: String.t(),
|
||||||
|
description: String.t(),
|
||||||
|
name: String.t(),
|
||||||
|
event: Event.t(),
|
||||||
|
sessions: [Session.t()]
|
||||||
|
}
|
||||||
|
|
||||||
|
@required_attrs [:name, :description, :color]
|
||||||
|
@optional_attrs [:event_id]
|
||||||
|
@attrs @required_attrs ++ @optional_attrs
|
||||||
|
|
||||||
schema "tracks" do
|
schema "tracks" do
|
||||||
field(:color, :string)
|
field(:color, :string)
|
||||||
field(:description, :string)
|
field(:description, :string)
|
||||||
field(:name, :string)
|
field(:name, :string)
|
||||||
|
|
||||||
belongs_to(:event, Event)
|
belongs_to(:event, Event)
|
||||||
has_many(:sessions, Session)
|
has_many(:sessions, Session)
|
||||||
|
|
||||||
@ -17,9 +33,10 @@ defmodule Mobilizon.Events.Track do
|
|||||||
end
|
end
|
||||||
|
|
||||||
@doc false
|
@doc false
|
||||||
|
@spec changeset(t, map) :: Ecto.Changeset.t()
|
||||||
def changeset(%Track{} = track, attrs) do
|
def changeset(%Track{} = track, attrs) do
|
||||||
track
|
track
|
||||||
|> cast(attrs, [:name, :description, :color, :event_id])
|
|> cast(attrs, @attrs)
|
||||||
|> validate_required([:name, :description, :color])
|
|> validate_required(@required_attrs)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -274,7 +274,7 @@ defmodule MobilizonWeb.Resolvers.Event do
|
|||||||
) do
|
) do
|
||||||
with {:ok, %Event{} = event} <- Mobilizon.Events.get_event(event_id),
|
with {:ok, %Event{} = event} <- Mobilizon.Events.get_event(event_id),
|
||||||
{:is_owned, %Actor{}} <- User.owns_actor(user, actor_id),
|
{:is_owned, %Actor{}} <- User.owns_actor(user, actor_id),
|
||||||
{:event_can_be_managed, true} <- Event.can_event_be_managed_by(event, actor_id),
|
{:event_can_be_managed, true} <- Event.can_be_managed_by(event, actor_id),
|
||||||
event <- Mobilizon.Events.delete_event!(event) do
|
event <- Mobilizon.Events.delete_event!(event) do
|
||||||
{:ok, %{id: event.id}}
|
{:ok, %{id: event.id}}
|
||||||
else
|
else
|
||||||
|
@ -461,8 +461,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
|||||||
local
|
local
|
||||||
) do
|
) do
|
||||||
with {:only_organizer, false} <-
|
with {:only_organizer, false} <-
|
||||||
{:only_organizer,
|
{:only_organizer, Participant.is_not_only_organizer(event_id, actor_id)},
|
||||||
Participant.check_that_participant_is_not_only_organizer(event_id, actor_id)},
|
|
||||||
{:ok, %Participant{} = participant} <-
|
{:ok, %Participant{} = participant} <-
|
||||||
Mobilizon.Events.get_participant(event_id, actor_id),
|
Mobilizon.Events.get_participant(event_id, actor_id),
|
||||||
{:ok, %Participant{} = participant} <- Mobilizon.Events.delete_participant(participant),
|
{:ok, %Participant{} = participant} <- Mobilizon.Events.delete_participant(participant),
|
||||||
|
12
mix.exs
12
mix.exs
@ -205,12 +205,12 @@ defmodule Mobilizon.Mixfile do
|
|||||||
Mobilizon.Events.Tag,
|
Mobilizon.Events.Tag,
|
||||||
Mobilizon.Events.TagRelations,
|
Mobilizon.Events.TagRelations,
|
||||||
Mobilizon.Events.Track,
|
Mobilizon.Events.Track,
|
||||||
Mobilizon.Event.EventCategoryEnum,
|
Mobilizon.Event.EventCategory,
|
||||||
Mobilizon.Events.CommentVisibilityEnum,
|
Mobilizon.Events.CommentVisibility,
|
||||||
Mobilizon.Events.EventStatusEnum,
|
Mobilizon.Events.EventStatus,
|
||||||
Mobilizon.Events.EventVisibilityEnum,
|
Mobilizon.Events.EventVisibility,
|
||||||
Mobilizon.Events.JoinOptionsEnum,
|
Mobilizon.Events.JoinOptions,
|
||||||
Mobilizon.Events.ParticipantRoleEnum,
|
Mobilizon.Events.ParticipantRole,
|
||||||
Mobilizon.Events.Tag.TitleSlug,
|
Mobilizon.Events.Tag.TitleSlug,
|
||||||
Mobilizon.Events.Tag.TitleSlug.Type,
|
Mobilizon.Events.Tag.TitleSlug.Type,
|
||||||
Mobilizon.Events.TagRelation,
|
Mobilizon.Events.TagRelation,
|
||||||
|
@ -2,20 +2,20 @@ defmodule Mobilizon.Repo.Migrations.FixEventVisibility do
|
|||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
Mobilizon.Events.EventVisibilityEnum.create_type()
|
Mobilizon.Events.EventVisibility.create_type()
|
||||||
Mobilizon.Events.EventStatusEnum.create_type()
|
Mobilizon.Events.EventStatus.create_type()
|
||||||
Mobilizon.Events.CommentVisibilityEnum.create_type()
|
Mobilizon.Events.CommentVisibility.create_type()
|
||||||
|
|
||||||
alter table(:events) do
|
alter table(:events) do
|
||||||
remove(:public)
|
remove(:public)
|
||||||
remove(:status)
|
remove(:status)
|
||||||
remove(:state)
|
remove(:state)
|
||||||
add(:visibility, Mobilizon.Events.EventVisibilityEnum.type())
|
add(:visibility, Mobilizon.Events.EventVisibility.type())
|
||||||
add(:status, Mobilizon.Events.EventStatusEnum.type())
|
add(:status, Mobilizon.Events.EventStatus.type())
|
||||||
end
|
end
|
||||||
|
|
||||||
alter table(:comments) do
|
alter table(:comments) do
|
||||||
add(:visibility, Mobilizon.Events.CommentVisibilityEnum.type())
|
add(:visibility, Mobilizon.Events.CommentVisibility.type())
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -32,8 +32,8 @@ defmodule Mobilizon.Repo.Migrations.FixEventVisibility do
|
|||||||
remove(:visibility)
|
remove(:visibility)
|
||||||
end
|
end
|
||||||
|
|
||||||
Mobilizon.Events.EventVisibilityEnum.drop_type()
|
Mobilizon.Events.EventVisibility.drop_type()
|
||||||
Mobilizon.Events.EventStatusEnum.drop_type()
|
Mobilizon.Events.EventStatus.drop_type()
|
||||||
Mobilizon.Events.CommentVisibilityEnum.drop_type()
|
Mobilizon.Events.CommentVisibility.drop_type()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
defmodule Mobilizon.Repo.Migrations.SplitEventVisibilityAndJoinOptions do
|
defmodule Mobilizon.Repo.Migrations.SplitEventVisibilityAndJoinOptions do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
alias Mobilizon.Events.EventVisibilityEnum
|
alias Mobilizon.Events.EventVisibility
|
||||||
alias Mobilizon.Events.JoinOptionsEnum
|
alias Mobilizon.Events.JoinOptions
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
EventVisibilityEnum has dropped some possible values, so we need to recreate it
|
EventVisibility has dropped some possible values, so we need to recreate it
|
||||||
|
|
||||||
Visibility allowed nullable values previously
|
Visibility allowed nullable values previously
|
||||||
"""
|
"""
|
||||||
def up do
|
def up do
|
||||||
execute("ALTER TABLE events ALTER COLUMN visibility TYPE VARCHAR USING visibility::text")
|
execute("ALTER TABLE events ALTER COLUMN visibility TYPE VARCHAR USING visibility::text")
|
||||||
EventVisibilityEnum.drop_type()
|
EventVisibility.drop_type()
|
||||||
EventVisibilityEnum.create_type()
|
EventVisibility.create_type()
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
"ALTER TABLE events ALTER COLUMN visibility TYPE event_visibility_type USING visibility::event_visibility_type"
|
"ALTER TABLE events ALTER COLUMN visibility TYPE event_visibility_type USING visibility::event_visibility"
|
||||||
)
|
)
|
||||||
|
|
||||||
JoinOptionsEnum.create_type()
|
JoinOptions.create_type()
|
||||||
|
|
||||||
alter table(:events) do
|
alter table(:events) do
|
||||||
add(:join_options, JoinOptionsEnum.type(), null: false, default: "free")
|
add(:join_options, JoinOptions.type(), null: false, default: "free")
|
||||||
end
|
end
|
||||||
|
|
||||||
execute("UPDATE events SET visibility = 'public' WHERE visibility IS NULL")
|
execute("UPDATE events SET visibility = 'public' WHERE visibility IS NULL")
|
||||||
|
|
||||||
alter table(:events) do
|
alter table(:events) do
|
||||||
modify(:visibility, EventVisibilityEnum.type(), null: false, default: "public")
|
modify(:visibility, EventVisibility.type(), null: false, default: "public")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -35,14 +35,14 @@ defmodule Mobilizon.Repo.Migrations.SplitEventVisibilityAndJoinOptions do
|
|||||||
remove(:join_options)
|
remove(:join_options)
|
||||||
end
|
end
|
||||||
|
|
||||||
JoinOptionsEnum.drop_type()
|
JoinOptions.drop_type()
|
||||||
|
|
||||||
execute("ALTER TABLE events ALTER COLUMN visibility TYPE VARCHAR USING visibility::text")
|
execute("ALTER TABLE events ALTER COLUMN visibility TYPE VARCHAR USING visibility::text")
|
||||||
EventVisibilityEnum.drop_type()
|
EventVisibility.drop_type()
|
||||||
EventVisibilityEnum.create_type()
|
EventVisibility.create_type()
|
||||||
|
|
||||||
execute(
|
execute(
|
||||||
"ALTER TABLE events ALTER COLUMN visibility TYPE event_visibility_type USING visibility::event_visibility_type"
|
"ALTER TABLE events ALTER COLUMN visibility TYPE event_visibility_type USING visibility::event_visibility"
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
defmodule Mobilizon.Repo.Migrations.MoveParticipantRoleToEnum do
|
defmodule Mobilizon.Repo.Migrations.MoveParticipantRoleToEnum do
|
||||||
use Ecto.Migration
|
use Ecto.Migration
|
||||||
alias Mobilizon.Events.ParticipantRoleEnum
|
alias Mobilizon.Events.ParticipantRole
|
||||||
|
|
||||||
def up do
|
def up do
|
||||||
ParticipantRoleEnum.create_type()
|
ParticipantRole.create_type()
|
||||||
|
|
||||||
alter table(:participants) do
|
alter table(:participants) do
|
||||||
add(:role_tmp, ParticipantRoleEnum.type(), default: "participant")
|
add(:role_tmp, ParticipantRole.type(), default: "participant")
|
||||||
end
|
end
|
||||||
|
|
||||||
execute("UPDATE participants set role_tmp = 'not_approved' where role = 0")
|
execute("UPDATE participants set role_tmp = 'not_approved' where role = 0")
|
||||||
@ -37,7 +37,7 @@ defmodule Mobilizon.Repo.Migrations.MoveParticipantRoleToEnum do
|
|||||||
remove(:role)
|
remove(:role)
|
||||||
end
|
end
|
||||||
|
|
||||||
ParticipantRoleEnum.drop_type()
|
ParticipantRole.drop_type()
|
||||||
|
|
||||||
rename(table(:participants), :role_tmp, to: :role)
|
rename(table(:participants), :role_tmp, to: :role)
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user