Improve look of dashboard page

This commit is contained in:
Peter Stockings
2025-11-21 11:27:56 +11:00
parent 64c3a4bbf7
commit eff379cf94

View File

@@ -2,117 +2,168 @@
{% block content %}
<div class="grid min-h-screen w-full lg:grid-cols-[280px_1fr]" data-id="1">
<div class="hidden border-r lg:block" data-id="2">
<div class="flex h-full max-h-screen flex-col gap-2" data-id="3">
<div class="flex h-[60px] items-center border-b px-6" data-id="4"><a
class="flex items-center gap-2 font-semibold" data-id="5" href="#"><svg
xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="h-6 w-6" data-id="6">
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"></path>
</svg><span class="leading-normal text-gray-800 text-base text-md font-semi-bold">Function
Manager</span></a><button
class="inline-flex items-center justify-center rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 border border-input bg-background hover:bg-accent hover:text-accent-foreground ml-auto h-8 w-8"
data-id="8"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"
stroke-linejoin="round" class="h-4 w-4" data-id="9">
<path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"></path>
<path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"></path>
</svg><span class="sr-only" data-id="10">Toggle notifications</span></button></div>
<div class="flex-1 overflow-auto py-2" data-id="11">
<nav class="grid items-start px-4 text-sm font-medium" data-id="12"><a
class="flex items-center gap-3 rounded-lg px-3 py-2 text-gray-500 transition-all hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-50 cursor-pointer"
href="{{ url_for('home.index') }}"><svg xmlns="http://www.w3.org/2000/svg" width="18"
height="18" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor"
class="size-6">
<div class="grid min-h-screen w-full lg:grid-cols-[280px_1fr] bg-gray-50 dark:bg-gray-900">
<!-- Sidebar -->
<div class="hidden border-r border-gray-200 dark:border-gray-800 lg:block bg-white dark:bg-gray-950">
<div class="flex h-full max-h-screen flex-col gap-2">
<div class="flex h-[60px] items-center border-b border-gray-200 dark:border-gray-800 px-6">
<a class="flex items-center gap-2 font-bold text-xl" href="#">
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"></path>
</svg>
</div>
<span class="text-gray-900 dark:text-white">Function</span>
</a>
</div>
<div class="flex-1 overflow-auto py-4">
<nav class="grid items-start px-4 text-sm font-medium gap-1">
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800 cursor-pointer group"
href="{{ url_for('home.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="group-hover:text-blue-600 transition-colors">
<path stroke-linecap="round" stroke-linejoin="round"
d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
</svg>
Dashboard
</a>
Home
</a><a
class="flex items-center gap-3 rounded-lg px-3 py-2 text-gray-500 transition-all hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-50 cursor-pointer"
data-id="15" hx-get="{{ url_for('http.overview') }}" hx-target="#container" hx-swap="innerHTML"
hx-push-url="true"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none"
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
<div class="my-2 border-t border-gray-100 dark:border-gray-800"></div>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800 cursor-pointer group"
hx-get="{{ url_for('http.overview') }}" hx-target="#container" hx-swap="innerHTML"
hx-push-url="true">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="group-hover:text-blue-600 transition-colors">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
</svg>
HTTP
</a><a
class="flex items-center gap-3 rounded-lg px-3 py-2 text-gray-500 transition-all hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-50 cursor-pointer"
data-id="17" hx-get="{{ url_for('timer.overview') }}" hx-target="#container" hx-swap="innerHTML"
hx-push-url="true"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none"
viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="size-6">
HTTP Functions
</a>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800 cursor-pointer group"
hx-get="{{ url_for('timer.overview') }}" hx-target="#container" hx-swap="innerHTML"
hx-push-url="true">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="group-hover:text-blue-600 transition-colors">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
Scheduled Jobs
</a>
Timer
</a><a
class="flex items-center gap-3 rounded-lg px-3 py-2 text-gray-500 transition-all hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-50 cursor-pointer"
data-id="18" href="{{ url_for('settings.index') }}">
<div class="my-2 border-t border-gray-100 dark:border-gray-800"></div>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800 cursor-pointer group"
href="{{ url_for('community.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor" class="size-6">
stroke-width="1.5" stroke="currentColor"
class="group-hover:text-blue-600 transition-colors">
<path stroke-linecap="round" stroke-linejoin="round"
d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
</svg>
Community
</a>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800 cursor-pointer group"
href="{{ url_for('settings.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor"
class="group-hover:text-blue-600 transition-colors">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 0 1 0 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 0 1 0-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281Z" />
<path stroke-linecap="round" stroke-linejoin="round"
d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
Settings
</a><a
class="flex items-center gap-3 rounded-lg px-3 py-2 text-gray-500 transition-all hover:text-gray-900 dark:text-gray-400 dark:hover:text-gray-50 cursor-pointer"
data-id="18" href="{{ url_for('community.index') }}">
<svg data-slot="icon" data-darkreader-inline-stroke="" width="18" height="18" fill="none"
stroke-width="1.5" stroke="currentColor" viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round"
d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z">
</path>
</svg>
Community
</a></nav>
</a>
</nav>
</div>
<div class="p-4 border-t border-gray-200 dark:border-gray-800">
<div class="bg-blue-50 dark:bg-blue-900/20 rounded-lg p-4">
<h4 class="text-sm font-semibold text-blue-900 dark:text-blue-100 mb-1">Need help?</h4>
<p class="text-xs text-blue-700 dark:text-blue-300 mb-3">Check our docs for guides and API
references.</p>
<a href="{{ url_for('documentation') }}"
class="text-xs font-medium text-blue-600 dark:text-blue-400 hover:underline">View Documentation
&rarr;</a>
</div>
</div>
</div>
</div>
<div class="flex flex-col" data-id="28">
<header class="flex h-14 lg:h-[60px] items-center gap-4 border-b px-6" data-id="29"><a class="lg:hidden"
data-id="30" href="#"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"
fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="h-6 w-6" data-id="31">
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"></path>
</svg><span class="sr-only" data-id="32">Home</span></a>
<div class="w-full flex-1" data-id="33">
</div>
<a class="inline-flex items-center justify-center text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 hover:bg-accent hover:text-accent-foreground rounded-full border border-gray-200 w-8 h-8 dark:border-gray-800 cursor-pointer"
data-id="40" type="button" id="radix-:r1u:" aria-haspopup="menu" aria-expanded="false"
data-state="closed" href="{{ url_for('auth.logout') }}">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round"
d="M17.982 18.725A7.488 7.488 0 0012 15.75a7.488 7.488 0 00-5.982 2.975m11.963 0a9 9 0 10-11.963 0m11.963 0A8.966 8.966 0 0112 21a8.966 8.966 0 01-5.982-2.275M15 9.75a3 3 0 11-6 0 3 3 0 016 0z" />
<!-- Main Content -->
<div class="flex flex-col">
<header
class="flex h-14 lg:h-[60px] items-center gap-4 border-b border-gray-200 dark:border-gray-800 bg-white dark:bg-gray-950 px-6 sticky top-0 z-10">
<a class="lg:hidden" href="#" id="mobile-menu-toggle">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
class="h-6 w-6 text-gray-600 dark:text-gray-400">
<path d="M3 12h18M3 6h18M3 18h18" />
</svg>
<span class="sr-only" data-id="42">Toggle user menu</span>
<span class="sr-only">Toggle menu</span>
</a>
<!-- Breadcrumbs -->
<div class="w-full flex-1">
<nav class="flex" aria-label="Breadcrumb">
<ol class="inline-flex items-center space-x-1 md:space-x-3">
<li class="inline-flex items-center">
<a href="{{ url_for('home.index') }}"
class="inline-flex items-center text-sm font-medium text-gray-500 hover:text-blue-600 dark:text-gray-400 dark:hover:text-white">
<svg class="w-3 h-3 mr-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"
fill="currentColor" viewBox="0 0 20 20">
<path
d="m19.707 9.293-2-2-7-7a1 1 0 0 0-1.414 0l-7 7-2 2a1 1 0 0 0 1.414 1.414L2 10.414V18a2 2 0 0 0 2 2h3a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1h3a2 2 0 0 0 2-2v-7.586l.293.293a1 1 0 0 0 1.414-1.414Z" />
</svg>
Home
</a>
</li>
<!-- Dynamic breadcrumbs could be injected here via blocks if needed -->
</ol>
</nav>
</div>
<!-- User Menu -->
<div class="flex items-center gap-4">
<a class="inline-flex items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background hover:bg-gray-100 dark:hover:bg-gray-800 rounded-full w-9 h-9 text-gray-500 dark:text-gray-400"
href="{{ url_for('auth.logout') }}" title="Sign out">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
stroke="currentColor" class="w-5 h-5">
<path stroke-linecap="round" stroke-linejoin="round"
d="M15.75 9V5.25A2.25 2.25 0 0013.5 3h-6a2.25 2.25 0 00-2.25 2.25v13.5A2.25 2.25 0 007.5 21h6a2.25 2.25 0 002.25-2.25V15m3 0l3-3m0 0l-3-3m3 3H9" />
</svg>
<span class="sr-only">Sign out</span>
</a>
</div>
</header>
<main class="flex flex-1 flex-col gap-4 p-4 md:p-6" data-id="50" id="container">
<main class="flex flex-1 flex-col gap-4 p-4 md:p-8 max-w-7xl mx-auto w-full" id="container">
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div
class="mb-4 p-4 rounded-lg {% if category == 'success' %}bg-green-100 text-green-700{% else %}bg-red-100 text-red-700{% endif %}">
class="mb-4 p-4 rounded-lg border {% if category == 'success' %}bg-green-50 border-green-200 text-green-700 dark:bg-green-900/20 dark:border-green-800 dark:text-green-300{% else %}bg-red-50 border-red-200 text-red-700 dark:bg-red-900/20 dark:border-red-800 dark:text-red-300{% endif %} flex items-center shadow-sm">
{% if category == 'success' %}
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
{% else %}
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
</svg>
{% endif %}
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block page %}
{{ render_block(app.jinja_env, "dashboard/http_functions/overview.html", "page",
http_functions=http_functions) }}
@@ -121,5 +172,121 @@
</div>
</div>
<!-- Mobile Sidebar Overlay -->
<div id="mobile-sidebar-overlay"
class="fixed inset-0 z-40 bg-black/50 hidden lg:hidden backdrop-blur-sm transition-opacity opacity-0"></div>
<!-- Mobile Sidebar -->
<div id="mobile-sidebar"
class="fixed inset-y-0 left-0 z-50 w-64 bg-white dark:bg-gray-950 shadow-xl transform -translate-x-full transition-transform duration-300 ease-in-out lg:hidden flex flex-col">
<div class="flex h-[60px] items-center border-b border-gray-200 dark:border-gray-800 px-6 justify-between">
<a class="flex items-center gap-2 font-bold text-xl" href="#">
<div class="w-8 h-8 bg-blue-600 rounded-lg flex items-center justify-center text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="m19 21-7-4-7 4V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v16z"></path>
</svg>
</div>
<span class="text-gray-900 dark:text-white">Function</span>
</a>
<button id="mobile-sidebar-close"
class="text-gray-500 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M18 6 6 18M6 6l12 12" />
</svg>
</button>
</div>
<div class="flex-1 overflow-auto py-4 px-4">
<!-- Mobile Nav Links (Duplicate of Desktop for simplicity, or use a macro) -->
<nav class="grid items-start gap-1 text-sm font-medium">
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800"
href="{{ url_for('home.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
d="M3 13.125C3 12.504 3.504 12 4.125 12h2.25c.621 0 1.125.504 1.125 1.125v6.75C7.5 20.496 6.996 21 6.375 21h-2.25A1.125 1.125 0 0 1 3 19.875v-6.75ZM9.75 8.625c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125v11.25c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V8.625ZM16.5 4.125c0-.621.504-1.125 1.125-1.125h2.25C20.496 3 21 3.504 21 4.125v15.75c0 .621-.504 1.125-1.125 1.125h-2.25a1.125 1.125 0 0 1-1.125-1.125V4.125Z" />
</svg>
Dashboard
</a>
<div class="my-2 border-t border-gray-100 dark:border-gray-800"></div>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800"
href="{{ url_for('http.overview') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 21a9.004 9.004 0 0 0 8.716-6.747M12 21a9.004 9.004 0 0 1-8.716-6.747M12 21c2.485 0 4.5-4.03 4.5-9S14.485 3 12 3m0 18c-2.485 0-4.5-4.03-4.5-9S9.515 3 12 3m0 0a8.997 8.997 0 0 1 7.843 4.582M12 3a8.997 8.997 0 0 0-7.843 4.582m15.686 0A11.953 11.953 0 0 1 12 10.5c-2.998 0-5.74-1.1-7.843-2.918m15.686 0A8.959 8.959 0 0 1 21 12c0 .778-.099 1.533-.284 2.253m0 0A17.919 17.919 0 0 1 12 16.5c-3.162 0-6.133-.815-8.716-2.247m0 0A9.015 9.015 0 0 1 3 12c0-1.605.42-3.113 1.157-4.418" />
</svg>
HTTP Functions
</a>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800"
href="{{ url_for('timer.overview') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
d="M12 6v6h4.5m4.5 0a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
Scheduled Jobs
</a>
<div class="my-2 border-t border-gray-100 dark:border-gray-800"></div>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800"
href="{{ url_for('community.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
d="M18 18.72a9.094 9.094 0 0 0 3.741-.479 3 3 0 0 0-4.682-2.72m.94 3.198.001.031c0 .225-.012.447-.037.666A11.944 11.944 0 0 1 12 21c-2.17 0-4.207-.576-5.963-1.584A6.062 6.062 0 0 1 6 18.719m12 0a5.971 5.971 0 0 0-.941-3.197m0 0A5.995 5.995 0 0 0 12 12.75a5.995 5.995 0 0 0-5.058 2.772m0 0a3 3 0 0 0-4.681 2.72 8.986 8.986 0 0 0 3.74.477m.94-3.197a5.971 5.971 0 0 0-.94 3.197M15 6.75a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm6 3a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Zm-13.5 0a2.25 2.25 0 1 1-4.5 0 2.25 2.25 0 0 1 4.5 0Z" />
</svg>
Community
</a>
<a class="flex items-center gap-3 rounded-lg px-3 py-2.5 text-gray-600 transition-all hover:text-gray-900 hover:bg-gray-100 dark:text-gray-400 dark:hover:text-gray-50 dark:hover:bg-gray-800"
href="{{ url_for('settings.index') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="none" viewBox="0 0 24 24"
stroke-width="1.5" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round"
d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.324.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.24-.438.613-.431.992a6.759 6.759 0 0 1 0 .255c-.007.378.138.75.43.99l1.005.828c.424.35.534.954.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.57 6.57 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.28c-.09.543-.56.941-1.11.941h-2.594c-.55 0-1.02-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.992a6.932 6.932 0 0 1 0-.255c.007-.378-.138-.75-.43-.99l-1.004-.828a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.087.22-.128.332-.183.582-.495.644-.869l.214-1.281Z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z" />
</svg>
Settings
</a>
</nav>
</div>
</div>
<script>
// Mobile Sidebar Toggle Logic
const mobileMenuToggle = document.getElementById('mobile-menu-toggle');
const mobileSidebar = document.getElementById('mobile-sidebar');
const mobileSidebarClose = document.getElementById('mobile-sidebar-close');
const mobileSidebarOverlay = document.getElementById('mobile-sidebar-overlay');
function toggleSidebar() {
const isHidden = mobileSidebar.classList.contains('-translate-x-full');
if (isHidden) {
// Open
mobileSidebar.classList.remove('-translate-x-full');
mobileSidebarOverlay.classList.remove('hidden');
// Small delay to allow display:block to apply before opacity transition
setTimeout(() => {
mobileSidebarOverlay.classList.remove('opacity-0');
}, 10);
} else {
// Close
mobileSidebar.classList.add('-translate-x-full');
mobileSidebarOverlay.classList.add('opacity-0');
setTimeout(() => {
mobileSidebarOverlay.classList.add('hidden');
}, 300); // Match transition duration
}
}
if (mobileMenuToggle) mobileMenuToggle.addEventListener('click', (e) => {
e.preventDefault();
toggleSidebar();
});
if (mobileSidebarClose) mobileSidebarClose.addEventListener('click', toggleSidebar);
if (mobileSidebarOverlay) mobileSidebarOverlay.addEventListener('click', toggleSidebar);
</script>
{% endblock %}