Make Categories a predefined list
Signed-off-by: Thomas Citharel <tcit@tcit.fr> Allow null values for categories for now Signed-off-by: Thomas Citharel <tcit@tcit.fr>
This commit is contained in:
@@ -1,26 +0,0 @@
|
||||
defmodule Mobilizon.Events.Category do
|
||||
@moduledoc """
|
||||
Represents a category for events
|
||||
"""
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Mobilizon.Events.Category
|
||||
use Arc.Ecto.Schema
|
||||
|
||||
schema "categories" do
|
||||
field(:description, :string)
|
||||
field(:picture, MobilizonWeb.Uploaders.Category.Type)
|
||||
field(:title, :string, null: false)
|
||||
|
||||
timestamps()
|
||||
end
|
||||
|
||||
@doc false
|
||||
def changeset(%Category{} = category, attrs) do
|
||||
category
|
||||
|> cast(attrs, [:title, :description])
|
||||
|> cast_attachments(attrs, [:picture])
|
||||
|> validate_required([:title])
|
||||
|> unique_constraint(:title)
|
||||
end
|
||||
end
|
||||
@@ -19,13 +19,21 @@ defenum(Mobilizon.Events.EventStatusEnum, :event_status_type, [
|
||||
:cancelled
|
||||
])
|
||||
|
||||
defenum(Mobilizon.Event.EventCategoryEnum, :event_category_type, [
|
||||
:business,
|
||||
:conference,
|
||||
:birthday,
|
||||
:demonstration,
|
||||
:meeting
|
||||
])
|
||||
|
||||
defmodule Mobilizon.Events.Event do
|
||||
@moduledoc """
|
||||
Represents an event
|
||||
"""
|
||||
use Ecto.Schema
|
||||
import Ecto.Changeset
|
||||
alias Mobilizon.Events.{Event, Participant, Tag, Category, Session, Track}
|
||||
alias Mobilizon.Events.{Event, Participant, Tag, Session, Track}
|
||||
alias Mobilizon.Actors.Actor
|
||||
alias Mobilizon.Addresses.Address
|
||||
|
||||
@@ -45,10 +53,10 @@ defmodule Mobilizon.Events.Event do
|
||||
field(:uuid, Ecto.UUID, default: Ecto.UUID.generate())
|
||||
field(:online_address, :string)
|
||||
field(:phone_address, :string)
|
||||
field(:category, :string)
|
||||
belongs_to(:organizer_actor, Actor, foreign_key: :organizer_actor_id)
|
||||
belongs_to(:attributed_to, Actor, foreign_key: :attributed_to_id)
|
||||
many_to_many(:tags, Tag, join_through: "events_tags")
|
||||
belongs_to(:category, Category)
|
||||
many_to_many(:participants, Actor, join_through: Participant)
|
||||
has_many(:tracks, Track)
|
||||
has_many(:sessions, Session)
|
||||
@@ -67,7 +75,7 @@ defmodule Mobilizon.Events.Event do
|
||||
:begins_on,
|
||||
:ends_on,
|
||||
:organizer_actor_id,
|
||||
:category_id,
|
||||
:category,
|
||||
:status,
|
||||
:visibility,
|
||||
:thumbnail,
|
||||
@@ -83,7 +91,7 @@ defmodule Mobilizon.Events.Event do
|
||||
:title,
|
||||
:begins_on,
|
||||
:organizer_actor_id,
|
||||
:category_id,
|
||||
:category,
|
||||
:url,
|
||||
:uuid
|
||||
])
|
||||
|
||||
@@ -27,7 +27,6 @@ defmodule Mobilizon.Events do
|
||||
order_by: [desc: :id],
|
||||
preload: [
|
||||
:organizer_actor,
|
||||
:category,
|
||||
:sessions,
|
||||
:tracks,
|
||||
:tags,
|
||||
@@ -145,7 +144,6 @@ defmodule Mobilizon.Events do
|
||||
where: e.uuid == ^uuid and e.visibility in [^:public, ^:unlisted],
|
||||
preload: [
|
||||
:organizer_actor,
|
||||
:category,
|
||||
:sessions,
|
||||
:tracks,
|
||||
:tags,
|
||||
@@ -164,7 +162,6 @@ defmodule Mobilizon.Events do
|
||||
|
||||
Repo.preload(event, [
|
||||
:organizer_actor,
|
||||
:category,
|
||||
:sessions,
|
||||
:tracks,
|
||||
:tags,
|
||||
@@ -182,7 +179,6 @@ defmodule Mobilizon.Events do
|
||||
where: e.url == ^url and e.visibility in [^:public, ^:unlisted],
|
||||
preload: [
|
||||
:organizer_actor,
|
||||
:category,
|
||||
:sessions,
|
||||
:tracks,
|
||||
:tags,
|
||||
@@ -205,7 +201,6 @@ defmodule Mobilizon.Events do
|
||||
where: e.url == ^url and e.visibility in [^:public, ^:unlisted],
|
||||
preload: [
|
||||
:organizer_actor,
|
||||
:category,
|
||||
:sessions,
|
||||
:tracks,
|
||||
:tags,
|
||||
@@ -350,110 +345,6 @@ defmodule Mobilizon.Events do
|
||||
Event.changeset(event, %{})
|
||||
end
|
||||
|
||||
alias Mobilizon.Events.Category
|
||||
|
||||
@doc """
|
||||
Returns the list of categories.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> list_categories()
|
||||
[%Category{}, ...]
|
||||
|
||||
"""
|
||||
def list_categories(page \\ nil, limit \\ nil) do
|
||||
Repo.all(
|
||||
Category
|
||||
|> paginate(page, limit)
|
||||
)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Gets a single category.
|
||||
|
||||
Raises `Ecto.NoResultsError` if the Category does not exist.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> get_category!(123)
|
||||
%Category{}
|
||||
|
||||
iex> get_category!(456)
|
||||
** (Ecto.NoResultsError)
|
||||
|
||||
"""
|
||||
def get_category!(id), do: Repo.get!(Category, id)
|
||||
|
||||
@spec get_category_by_title(String.t()) :: Category.t() | nil
|
||||
def get_category_by_title(title) when is_binary(title) do
|
||||
Repo.get_by(Category, title: title)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Creates a category.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> create_category(%{field: value})
|
||||
{:ok, %Category{}}
|
||||
|
||||
iex> create_category(%{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def create_category(attrs \\ %{}) do
|
||||
%Category{}
|
||||
|> Category.changeset(attrs)
|
||||
|> Repo.insert()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Updates a category.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> update_category(category, %{field: new_value})
|
||||
{:ok, %Category{}}
|
||||
|
||||
iex> update_category(category, %{field: bad_value})
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def update_category(%Category{} = category, attrs) do
|
||||
category
|
||||
|> Category.changeset(attrs)
|
||||
|> Repo.update()
|
||||
end
|
||||
|
||||
@doc """
|
||||
Deletes a Category.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> delete_category(category)
|
||||
{:ok, %Category{}}
|
||||
|
||||
iex> delete_category(category)
|
||||
{:error, %Ecto.Changeset{}}
|
||||
|
||||
"""
|
||||
def delete_category(%Category{} = category) do
|
||||
Repo.delete(category)
|
||||
end
|
||||
|
||||
@doc """
|
||||
Returns an `%Ecto.Changeset{}` for tracking category changes.
|
||||
|
||||
## Examples
|
||||
|
||||
iex> change_category(category)
|
||||
%Ecto.Changeset{source: %Category{}}
|
||||
|
||||
"""
|
||||
def change_category(%Category{} = category) do
|
||||
Category.changeset(category, %{})
|
||||
end
|
||||
|
||||
alias Mobilizon.Events.Tag
|
||||
|
||||
@doc """
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
defmodule MobilizonWeb.Resolvers.Category do
|
||||
@moduledoc """
|
||||
Handles the category-related GraphQL calls
|
||||
"""
|
||||
require Logger
|
||||
alias Mobilizon.Actors.User
|
||||
|
||||
###
|
||||
# TODO : Refactor this into MobilizonWeb.API.Categories when a standard AS category is defined
|
||||
###
|
||||
def list_categories(_parent, %{page: page, limit: limit}, _resolution) do
|
||||
categories =
|
||||
Mobilizon.Events.list_categories(page, limit)
|
||||
|> Enum.map(fn category ->
|
||||
urls = MobilizonWeb.Uploaders.Category.urls({category.picture, category})
|
||||
Map.put(category, :picture, %{url: urls.original, url_thumbnail: urls.thumb})
|
||||
end)
|
||||
|
||||
{:ok, categories}
|
||||
end
|
||||
|
||||
def create_category(_parent, %{title: title, picture: picture, description: description}, %{
|
||||
context: %{current_user: %User{} = _user}
|
||||
}) do
|
||||
with {:ok, category} <-
|
||||
Mobilizon.Events.create_category(%{
|
||||
title: title,
|
||||
description: description,
|
||||
picture: picture
|
||||
}),
|
||||
urls <- MobilizonWeb.Uploaders.Category.urls({category.picture, category}) do
|
||||
Logger.info("Created category " <> title)
|
||||
{:ok, Map.put(category, :picture, %{url: urls.original, url_thumbnail: urls.thumb})}
|
||||
else
|
||||
{:error, %Ecto.Changeset{errors: errors} = _changeset} ->
|
||||
# This is pretty ridiculous for changeset to error
|
||||
errors =
|
||||
Enum.into(errors, %{})
|
||||
|> Enum.map(fn {key, {value, _}} -> Atom.to_string(key) <> ": " <> value end)
|
||||
|
||||
{:error, errors}
|
||||
end
|
||||
end
|
||||
|
||||
def create_category(_parent, _args, %{}) do
|
||||
{:error, "You are not allowed to create a category if not connected"}
|
||||
end
|
||||
end
|
||||
@@ -130,7 +130,6 @@ defmodule MobilizonWeb.Schema do
|
||||
import_fields(:group_queries)
|
||||
import_fields(:event_queries)
|
||||
import_fields(:participant_queries)
|
||||
import_fields(:category_queries)
|
||||
import_fields(:tag_queries)
|
||||
end
|
||||
|
||||
@@ -142,7 +141,6 @@ defmodule MobilizonWeb.Schema do
|
||||
import_fields(:person_mutations)
|
||||
import_fields(:group_mutations)
|
||||
import_fields(:event_mutations)
|
||||
import_fields(:category_mutations)
|
||||
import_fields(:comment_mutations)
|
||||
import_fields(:participant_mutations)
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||
import Absinthe.Resolution.Helpers, only: [dataloader: 1]
|
||||
import_types(MobilizonWeb.Schema.AddressType)
|
||||
import_types(MobilizonWeb.Schema.Events.ParticipantType)
|
||||
import_types(MobilizonWeb.Schema.Events.CategoryType)
|
||||
import_types(MobilizonWeb.Schema.TagType)
|
||||
alias MobilizonWeb.Resolvers
|
||||
|
||||
@@ -44,7 +43,7 @@ defmodule MobilizonWeb.Schema.EventType do
|
||||
description: "The event's tags"
|
||||
)
|
||||
|
||||
field(:category, :category, description: "The event's category")
|
||||
field(:category, :string, description: "The event's category")
|
||||
|
||||
field(:participants, list_of(:participant),
|
||||
resolve: &MobilizonWeb.Resolvers.Event.list_participants_for_event/3,
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
defmodule MobilizonWeb.Schema.Events.CategoryType do
|
||||
@moduledoc """
|
||||
Schema representation for Category
|
||||
"""
|
||||
use Absinthe.Schema.Notation
|
||||
alias MobilizonWeb.Resolvers
|
||||
|
||||
@desc "A category"
|
||||
object :category do
|
||||
field(:id, :id, description: "The category's ID")
|
||||
field(:description, :string, description: "The category's description")
|
||||
field(:picture, :picture, description: "The category's picture")
|
||||
field(:title, :string, description: "The category's title")
|
||||
end
|
||||
|
||||
object :category_queries do
|
||||
@desc "Get the list of categories"
|
||||
field :categories, non_null(list_of(:category)) do
|
||||
arg(:page, :integer, default_value: 1)
|
||||
arg(:limit, :integer, default_value: 10)
|
||||
resolve(&Resolvers.Category.list_categories/3)
|
||||
end
|
||||
end
|
||||
|
||||
object :category_mutations do
|
||||
@desc "Create a category with a title, description and picture"
|
||||
field :create_category, type: :category do
|
||||
arg(:title, non_null(:string))
|
||||
arg(:description, non_null(:string))
|
||||
arg(:picture, non_null(:upload))
|
||||
resolve(&Resolvers.Category.create_category/3)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -30,10 +30,9 @@ defmodule MobilizonWeb.Uploaders.Category do
|
||||
"#{title}_#{version}"
|
||||
end
|
||||
|
||||
# TODO : When we're sure creating a category is secured and made possible only for admins, use category name
|
||||
# Override the storage directory:
|
||||
def storage_dir(_, _) do
|
||||
"uploads/categories/"
|
||||
"uploads/event/"
|
||||
end
|
||||
|
||||
# Provide a default URL if there hasn't been a file uploaded
|
||||
@@ -1,6 +1,5 @@
|
||||
defmodule MobilizonWeb.ActivityPub.ObjectView do
|
||||
use MobilizonWeb, :view
|
||||
alias MobilizonWeb.ActivityPub.ObjectView
|
||||
alias Mobilizon.Service.ActivityPub.Utils
|
||||
|
||||
def render("event.json", %{event: event}) do
|
||||
@@ -9,7 +8,7 @@ defmodule MobilizonWeb.ActivityPub.ObjectView do
|
||||
"actor" => event["actor"],
|
||||
"id" => event["id"],
|
||||
"name" => event["title"],
|
||||
"category" => render_one(event["category"], ObjectView, "category.json", as: :category),
|
||||
"category" => event["category"],
|
||||
"content" => event["summary"],
|
||||
"mediaType" => "text/html"
|
||||
# "published" => Timex.format!(event.inserted_at, "{ISO:Extended}"),
|
||||
@@ -35,15 +34,4 @@ defmodule MobilizonWeb.ActivityPub.ObjectView do
|
||||
|
||||
Map.merge(comment, Utils.make_json_ld_header())
|
||||
end
|
||||
|
||||
def render("category.json", %{category: category}) when not is_nil(category) do
|
||||
%{
|
||||
"identifier" => category.id,
|
||||
"name" => category.title
|
||||
}
|
||||
end
|
||||
|
||||
def render("category.json", %{category: _category}) do
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,7 +11,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
"""
|
||||
|
||||
alias Mobilizon.Events
|
||||
alias Mobilizon.Events.{Event, Category, Comment}
|
||||
alias Mobilizon.Events.{Event, Comment}
|
||||
alias Mobilizon.Service.ActivityPub.Transmogrifier
|
||||
alias Mobilizon.Service.WebFinger
|
||||
alias Mobilizon.Activity
|
||||
@@ -565,23 +565,8 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
# TODO : Use MobilizonWeb.API instead
|
||||
# TODO : refactor me and move me somewhere else!
|
||||
# TODO : also, there should be a form of cache that allows this to be more efficient
|
||||
category =
|
||||
if is_nil(ical_event.categories) do
|
||||
nil
|
||||
else
|
||||
ical_category = ical_event.categories |> hd() |> String.downcase()
|
||||
|
||||
case ical_category |> Events.get_category_by_title() do
|
||||
nil ->
|
||||
case Events.create_category(%{"title" => ical_category}) do
|
||||
{:ok, %Category{} = category} -> category
|
||||
_ -> nil
|
||||
end
|
||||
|
||||
category ->
|
||||
category
|
||||
end
|
||||
end
|
||||
# ical_event.categories should be tags
|
||||
|
||||
{:ok, event} =
|
||||
Events.create_event(%{
|
||||
@@ -591,8 +576,7 @@ defmodule Mobilizon.Service.ActivityPub do
|
||||
updated_at: ical_event.stamp,
|
||||
description: ical_event.description |> sanitize_ical_event_strings,
|
||||
title: ical_event.summary |> sanitize_ical_event_strings,
|
||||
organizer_actor: actor,
|
||||
category: category
|
||||
organizer_actor: actor
|
||||
})
|
||||
|
||||
event_to_activity(event, false)
|
||||
|
||||
@@ -117,7 +117,7 @@ defmodule Mobilizon.Service.ActivityPub.Utils do
|
||||
"description" => object["content"],
|
||||
"organizer_actor_id" => actor_id,
|
||||
"begins_on" => object["begins_on"],
|
||||
"category_id" => Events.get_category_by_title(object["category"]).id,
|
||||
"category" => object["category"],
|
||||
"url" => object["id"],
|
||||
"uuid" => object["uuid"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user