mirror of
https://github.com/ClaperCo/Claper.git
synced 2026-02-24 12:09:59 +01:00
317 lines
12 KiB
Plaintext
317 lines
12 KiB
Plaintext
<!DOCTYPE html>
|
|
<html lang="en" data-theme="light">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
{csrf_meta_tag()}
|
|
<.live_title suffix=" · Claper Admin">
|
|
{assigns[:page_title] || "Admin Dashboard"}
|
|
</.live_title>
|
|
<link phx-track-static rel="stylesheet" href="/assets/app.css" />
|
|
<link phx-track-static rel="stylesheet" href="/assets/admin.css" />
|
|
<link rel="icon" type="image/png" href="/images/favicon.png" />
|
|
<script defer phx-track-static type="text/javascript" src="/assets/app.js">
|
|
</script>
|
|
</head>
|
|
<body>
|
|
<div class="drawer lg:drawer-open">
|
|
<input id="drawer-toggle" type="checkbox" class="drawer-toggle" />
|
|
|
|
<div class="drawer-content flex flex-col">
|
|
<!-- Navbar for mobile -->
|
|
<div class="navbar lg:hidden bg-base-100 shadow-lg">
|
|
<div class="flex-none">
|
|
<label for="drawer-toggle" class="btn btn-square btn-ghost drawer-button">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
class="inline-block w-5 h-5 stroke-current"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M4 6h16M4 12h16M4 18h16"
|
|
>
|
|
</path>
|
|
</svg>
|
|
</label>
|
|
</div>
|
|
<div class="flex-1">
|
|
<a href={~p"/admin"} class="btn btn-ghost normal-case text-xl">
|
|
<img src="/images/logo.svg" class="h-24 mr-2" /> {gettext("Admin")}
|
|
</a>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Page content -->
|
|
<main class="flex-1 overflow-y-auto bg-base-200 p-4 lg:p-8">
|
|
<!-- Toast container for flash messages -->
|
|
<div class="toast toast-top toast-end" id="flash-messages">
|
|
<%= if Phoenix.Flash.get(@flash, :info) do %>
|
|
<div class="alert alert-info shadow-lg">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
class="stroke-current shrink-0 w-6 h-6"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
>
|
|
</path>
|
|
</svg>
|
|
<span>{Phoenix.Flash.get(@flash, :info)}</span>
|
|
<button class="btn btn-ghost btn-xs" onclick="this.parentElement.remove()">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M6 18L18 6M6 6l12 12"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<% end %>
|
|
|
|
<%= if Phoenix.Flash.get(@flash, :success) do %>
|
|
<div class="alert alert-success shadow-lg">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
class="stroke-current shrink-0 h-6 w-6"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
<span>{Phoenix.Flash.get(@flash, :success)}</span>
|
|
<button class="btn btn-ghost btn-xs" onclick="this.parentElement.remove()">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M6 18L18 6M6 6l12 12"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<% end %>
|
|
|
|
<%= if Phoenix.Flash.get(@flash, :warning) do %>
|
|
<div class="alert alert-warning shadow-lg">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
class="stroke-current shrink-0 h-6 w-6"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"
|
|
/>
|
|
</svg>
|
|
<span>{Phoenix.Flash.get(@flash, :warning)}</span>
|
|
<button class="btn btn-ghost btn-xs" onclick="this.parentElement.remove()">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M6 18L18 6M6 6l12 12"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<% end %>
|
|
|
|
<%= if Phoenix.Flash.get(@flash, :error) do %>
|
|
<div class="alert alert-error shadow-lg">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
class="stroke-current shrink-0 h-6 w-6"
|
|
fill="none"
|
|
viewBox="0 0 24 24"
|
|
>
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z"
|
|
/>
|
|
</svg>
|
|
<span>{Phoenix.Flash.get(@flash, :error)}</span>
|
|
<button class="btn btn-ghost btn-xs" onclick="this.parentElement.remove()">
|
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M6 18L18 6M6 6l12 12"
|
|
/>
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
<% end %>
|
|
</div>
|
|
<div class="p-8 md:p-16">
|
|
{@inner_content}
|
|
</div>
|
|
</main>
|
|
</div>
|
|
|
|
<!-- Sidebar -->
|
|
<div class="drawer-side">
|
|
<label for="drawer-toggle" class="drawer-overlay"></label>
|
|
<aside class="bg-base-100 min-h-full px-12">
|
|
<div class="flex items-center p-5 gap-x-3">
|
|
<img src="/images/logo.svg" class="h-24" />
|
|
<h1 class="text-xl font-bold !font-display">{gettext("Admin")}</h1>
|
|
</div>
|
|
<ul class="menu">
|
|
<li>
|
|
<.link
|
|
patch={~p"/admin"}
|
|
class={"#{if @conn.path_info == ["admin"], do: "active", else: ""}"}
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6"
|
|
/>
|
|
</svg>
|
|
{gettext("Dashboard")}
|
|
</.link>
|
|
</li>
|
|
<li>
|
|
<.link
|
|
patch={~p"/admin/events"}
|
|
class={"#{if @conn.path_info == ["admin", "events"], do: "active", else: ""}"}
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
|
|
/>
|
|
</svg>
|
|
{gettext("Events")}
|
|
</.link>
|
|
</li>
|
|
<li>
|
|
<.link
|
|
patch={~p"/admin/users"}
|
|
class={"#{if @conn.path_info == ["admin", "users"], do: "active", else: ""}"}
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 4.354a4 4 0 110 5.292M15 21H3v-1a6 6 0 0112 0v1zm0 0h6v-1a6 6 0 00-9-5.197M13 7a4 4 0 11-8 0 4 4 0 018 0z"
|
|
/>
|
|
</svg>
|
|
{gettext("Users")}
|
|
</.link>
|
|
</li>
|
|
<%!-- <li>
|
|
<.link
|
|
patch={~p"/admin/oidc_providers"}
|
|
class={"#{if @conn.path_info == ["admin", "oidc_providers"], do: "active", else: ""}"}
|
|
>
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z"
|
|
/>
|
|
</svg>
|
|
{gettext("OIDC Providers")}
|
|
</.link>
|
|
</li> --%>
|
|
|
|
<div class="divider"></div>
|
|
|
|
<li>
|
|
<a href="https://docs.claper.co" target="_blank" rel="noopener noreferrer">
|
|
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"
|
|
/>
|
|
</svg>
|
|
{gettext("Documentation")}
|
|
<svg class="w-3 h-3 ml-auto" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
|
|
/>
|
|
</svg>
|
|
</a>
|
|
</li>
|
|
|
|
<div class="mt-auto pt-4">
|
|
<li>
|
|
<a href={~p"/events"} class="btn btn-outline btn-sm">
|
|
<svg class="w-3 h-3" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path
|
|
stroke-linecap="round"
|
|
stroke-linejoin="round"
|
|
stroke-width="2"
|
|
d="M10 19l-7-7m0 0l7-7m-7 7h18"
|
|
/>
|
|
</svg>
|
|
{gettext("Back to app")}
|
|
</a>
|
|
</li>
|
|
</div>
|
|
</ul>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Auto-dismiss flash messages script -->
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Auto-dismiss flash messages after 5 seconds
|
|
const flashMessages = document.querySelectorAll('#flash-messages .alert');
|
|
if (flashMessages.length > 0) {
|
|
setTimeout(function() {
|
|
flashMessages.forEach(function(message) {
|
|
if (document.body.contains(message)) {
|
|
message.style.transition = 'opacity 0.5s ease';
|
|
message.style.opacity = '0';
|
|
|
|
setTimeout(function() {
|
|
message.remove();
|
|
}, 500);
|
|
}
|
|
});
|
|
}, 5000);
|
|
}
|
|
});
|
|
</script>
|
|
</body>
|
|
</html>
|