ferne/lib/ferne/blockdb.ex

203 lines
4.8 KiB
Elixir

defmodule Ferne.BlockDb do
@moduledoc """
Keeps a list of blocks and various handy functions to access info about them.
"""
alias Ferne.Repo
alias Ferne.{Event, Block}
import Ecto.Query
@blocks %{
"custom_fields" => Ferne.BlockDb.CustomFields,
"discord_login" => Ferne.BlockDb.DiscordLogin,
"ffxiv_roles" => Ferne.BlockDb.FFXIVRoles,
"parties" => Ferne.BlockDb.Parties,
"titles" => Ferne.BlockDb.Titles
}
## Single Block Queries
def block_description(block) do
@blocks[block].description()
end
def block_id(block) do
@blocks[block].id()
end
def block_name(block) do
@blocks[block].name()
end
def block_has_settings?(block) do
@blocks[block].has_settings()
end
def block_has_special_section?(block) do
@blocks[block].has_special_section()
end
def block_extends_signup_page?(block) do
@blocks[block].extends_signup_page()
end
def block_interact_with_attendee?(block) do
@blocks[block].interacts_with_attendee()
end
def block_special_section_icon(block) do
@blocks[block].special_section_icon()
end
def block_special_section_name(block) do
@blocks[block].special_section_name()
end
def has_block?(blocks, id) do
blocks
|> Enum.map(& &1.identifier)
|> Enum.member?(id)
end
def has_block_with_special_section?(blocks) do
blocks
|> Enum.map(& &1.identifier)
|> Enum.any?(&block_has_special_section?/1)
end
def block_has_data?(blocks, id) do
block = Enum.find(blocks, &(&1.identifier == id))
block.data["data"] && !Enum.empty?(block.data["data"])
end
def block_data_or_default(block, key, default) do
if block.data && block.data["data"] do
block.data["data"][key] || default
else
default
end
end
def find_block(blocks, id) do
Enum.find(blocks, &(&1.identifier == id))
end
## Controller Queries
@doc """
Handles a GET request for a block setting page
"""
def block_controller_get(conn, block, event) do
if block_has_settings?(block) do
@blocks[block].controller_get(conn, event)
end
end
@doc """
Handles a POST request for a block setting page.
"""
def block_controller_post(conn, block, event, params) do
if block_has_settings?(block) do
@blocks[block].controller_post(conn, event, params)
end
end
@doc """
Handles a GET request for a block special page.
"""
def block_controller_special_get(conn, block, event) do
if block_has_special_section?(block) do
@blocks[block].controller_special_get(conn, event)
end
end
@doc """
Handles a POST request for a block special page.
"""
def block_controller_special_post(conn, block, event, params) do
if block_has_special_section?(block) do
@blocks[block].controller_special_post(conn, event, params)
end
end
## Insertion Queries
@doc """
Insert a block.
"""
def create_block(attrs, event) do
%Block{}
|> Block.change_block(attrs)
|> Ecto.Changeset.change(event_id: event.id)
|> Repo.insert()
end
## Modification Queries
@doc """
Delete a block.
"""
def delete_block(block) do
Repo.delete(block)
end
## Event-based Queries
@doc """
Gets a single, specified block for an event.
"""
def get_block_for_event(id, event) do
query =
from b in Block,
where: b.identifier == ^id and b.event_id == ^event.id
Repo.one(query)
end
@doc """
Get blocks that are in use for an event.
"""
def get_blocks_for_event(event) do
query =
from e in Event,
where: e.id == ^event.id,
join: b in Block,
on: b.event_id == e.id,
select: b
Repo.all(query)
end
@doc """
Get blocks that are not used for an event. Uses a list of used
blocks to avoid a query, since it's supposed to be used with the prior
function.
"""
def get_unused_blocks_for_event(used_blocks) do
ids = used_blocks |> Enum.map(& &1.identifier)
Block.valid_ids()
|> Enum.reject(&Enum.member?(ids, &1))
end
## Display Queries
@doc """
Gets a list of all enabled block metadata. This returns a list of "headers" to be matched with
what's in an attendees `custom_data` field.
"""
def get_metadata_for_event(event) do
[]
|> get_metadata_for_block(event, "custom_fields")
|> get_metadata_for_block(event, "discord_login")
|> get_metadata_for_block(event, "ffxiv_roles")
|> get_metadata_for_block(event, "parties")
|> get_metadata_for_block(event, "titles")
|> Enum.concat()
end
def get_metadata_for_block(meta, event, block_id) do
if event.blocks && Enum.map(event.blocks, & &1.identifier) |> Enum.member?(block_id) do
data = Enum.find(event.blocks, &(&1.identifier == block_id)).data["data"]
[@blocks[block_id].get_metadata!(data) | meta]
else
meta
end
end
end