Commit 5308961c authored by Raphael Costa's avatar Raphael Costa
Browse files

Add basic resource definition

parent 4438083e
defmodule AdminElf.Admin do
@type resources_map() :: %{required(atom()) => module() | resources_map()}
# TODO finish defining sidebar item types
@type sidebar_item() :: %{type: :dashboard} | %{type: :resource} | %{type: :group}
@type sidebar_definition() :: [sidebar_item()]
@callback resources(conn :: Plug.Conn.t()) :: resources_map()
@callback sidebar(conn :: Plug.Conn.t()) :: sidebar_definition()
end
defmodule AdminElf.Plug do
use Plug.Builder
import Plug.Conn
plug AdminElfWeb.Router
def call(conn, opts) do
conn
|> put_private(AdminElf, %{
admin: Keyword.fetch!(opts, :admin)
})
|> super(opts)
end
end
defmodule AdminElf.Resource do
@callback name() :: String.t()
@callback plural_name() :: String.t()
@callback icon() :: String.t()
def get_name(conn, admin, id) do
fetch_resource!(conn, admin, id).name()
end
def get_plural_name(conn, admin, id) do
fetch_resource!(conn, admin, id).plural_name()
end
def get_icon(conn, admin, id) do
fetch_resource!(conn, admin, id).icon()
end
defp fetch_resource!(conn, admin, id) do
path = Enum.map(id, &Access.key!/1)
get_in(admin.resources(conn), path)
end
end
defmodule AdminElf.SidebarHelpers do
def dashboard do
%{type: :dashboard}
end
def resource(id) do
%{type: :resource, resource: id}
end
def group(title, opts) do
%{
type: :group,
title: title,
resources: Keyword.fetch!(opts, :resources),
icon: Keyword.get(opts, :icon)
}
end
end
......@@ -68,6 +68,8 @@ defmodule AdminElfWeb do
import AdminElfWeb.ErrorHelpers
import AdminElfWeb.Gettext
import AdminElfWeb.ViewHelpers
alias AdminElfWeb.Routes
end
end
......
......@@ -12,34 +12,47 @@
<div class="flex h-screen">
<section class="w-80 bg-purple-700 shadow-2xl">
<h1 class="text-purple-100 text-4xl p-12 text-center bg-purple-800 floating-cogs-bg">Admin Elf</h1>
<a class="block text-purple-100 hover:bg-purple-900 transition text-xl p-4" href="#">Home</a>
<div x-data="{ open: false }">
<a
class="block text-purple-100 hover:bg-purple-900 transition text-xl p-4"
href="javascript:void(0)"
@click="open = !open"
:class="{ 'bg-purple-900': open }"
>
Accounts
</a>
<div x-show="open" class="bg-purple-800">
<a class="block text-purple-100 hover:bg-purple-900 transition text-lg pl-6 p-3" href="#">Users</a>
<a class="block text-purple-100 hover:bg-purple-900 transition text-lg pl-6 p-3" href="#">Admins</a>
</div>
</div>
<div x-data="{ open: false }">
<a
class="block text-purple-100 hover:bg-purple-900 transition text-xl p-4"
href="javascript:void(0)"
@click="open = !open"
:class="{ 'bg-purple-900': open }"
>
Courses
</a>
<div x-show="open" class="bg-purple-800">
<a class="block text-purple-100 hover:bg-purple-900 transition text-lg pl-6 p-3" href="#">Sections</a>
<a class="block text-purple-100 hover:bg-purple-900 transition text-lg pl-6 p-3" href="#">Sub-sections</a>
</div>
<%= for sidebar_item <- sidebar(@conn) do %>
<%= case sidebar_item.type do %>
<% :dashboard -> %>
<a class="flex items-center gap-3 text-purple-100 hover:bg-purple-900 transition text-xl px-4 h-14" href="#">
<%= feather_icon(@conn, "home") %> Home
</a>
<% :resource -> %>
<a class="flex items-center gap-3 text-purple-100 hover:bg-purple-900 transition text-xl px-4 h-14" href="#">
<%= resource_icon(@conn, sidebar_item.resource) %>
<%= @conn |> resource_plural_name(sidebar_item.resource) |> capitalize() %>
</a>
<% :group -> %>
<div x-data="{ open: false }">
<a
class="flex items-center gap-3 text-purple-100 hover:bg-purple-900 transition text-xl px-4 h-14"
href="javascript:void(0)"
@click="open = !open"
:class="{ 'bg-purple-900': open }"
>
<%= if sidebar_item.icon, do: feather_icon(@conn, sidebar_item.icon) %>
<div class="flex flex-grow justify-between">
<%= sidebar_item.title %>
<div class="flex items-center" x-show="!open">
<%= feather_icon(@conn, "plus") %>
</div>
<div class="flex items-center" x-show="open">
<%= feather_icon(@conn, "minus") %>
</div>
</div>
</a>
<div x-show="open" class="bg-purple-800">
<%= for resource <- sidebar_item.resources do %>
<a class="flex items-center gap-3 text-purple-100 hover:bg-purple-900 transition text-lg pl-7 h-10" href="#">
<%= resource_icon(@conn, resource) %>
<%= @conn |> resource_plural_name(resource) |> capitalize() %>
</a>
<% end %>
</div>
</div>
<% end %>
<% end %>
</div>
</section>
<section class="flex-grow bg-gray-200 p-8">
......
defmodule AdminElfWeb.ViewHelpers do
use Phoenix.HTML
alias AdminElf.Resource
alias AdminElfWeb.Routes
def capitalize(string) do
String.capitalize(string)
end
def feather_icon(conn, icon, opts \\ []) do
default_attrs = [
width: "24",
height: "24",
fill: "none",
stroke: "currentColor",
stroke_width: "2",
stroke_linecap: "round",
stroke_linejoin: "round"
]
content_tag(:svg, default_attrs) do
tag(:use, ["xlink:href": Routes.static_path(conn, "/icons/feather-sprite.svg\##{icon}")])
end
end
def resource_name(conn, id) do
Resource.get_name(conn, get_admin(conn), id)
end
def resource_plural_name(conn, id) do
Resource.get_plural_name(conn, get_admin(conn), id)
end
def resource_icon(conn, id, opts \\ []) do
icon = Resource.get_icon(conn, get_admin(conn), id)
if icon do
feather_icon(conn, icon, opts)
end
end
def sidebar(conn) do
get_admin(conn).sidebar(conn)
end
defp get_admin(conn) do
conn.private
|> Map.fetch!(AdminElf)
|> Map.fetch!(:admin)
end
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment