Use top menu structure
This commit is contained in:
parent
5aae477a17
commit
8b49d05e1d
4 changed files with 221 additions and 195 deletions
|
@ -1,4 +1,4 @@
|
|||
{% load static %}
|
||||
{% load i18n static %}
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
@ -20,49 +20,48 @@
|
|||
<body hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'>
|
||||
<script src="{% static 'mazer/static/js/initTheme.js' %}"></script>
|
||||
<div id="app">
|
||||
{% include 'includes/sidebar.html' %}
|
||||
<div id="main">
|
||||
<header class="mb-3">
|
||||
<a href="#" class="burger-btn d-block d-xl-none">
|
||||
<i class="bi bi-justify fs-3"></i>
|
||||
</a>
|
||||
</header>
|
||||
<div class="page-heading">
|
||||
<h3>
|
||||
{% block page_title %}
|
||||
Dashboard
|
||||
{% endblock page_title %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="page-content">
|
||||
{% for message in messages %}
|
||||
{% include "includes/message.html" %}
|
||||
{% endfor %}
|
||||
{% block content %}
|
||||
<section class="section">
|
||||
<div class="card">
|
||||
{% block card_header %}{% endblock %}
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
{% block card_content %}
|
||||
{% endblock card_content %}
|
||||
<div id="main" class="layout-horizontal">
|
||||
{% include 'includes/header.html' %}
|
||||
<div class="content-wrapper container">
|
||||
<div class="page-heading">
|
||||
<h3>
|
||||
{% block page_title %}
|
||||
Dashboard
|
||||
{% endblock page_title %}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="page-content">
|
||||
{% for message in messages %}
|
||||
{% include "includes/message.html" %}
|
||||
{% endfor %}
|
||||
{% block content %}
|
||||
<section class="section">
|
||||
<div class="card">
|
||||
{% block card_header %}{% endblock %}
|
||||
<div class="card-content">
|
||||
<div class="card-body">
|
||||
{% block card_content %}
|
||||
{% endblock card_content %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock content %}
|
||||
</section>
|
||||
{% endblock content %}
|
||||
</div>
|
||||
</div>
|
||||
<footer>
|
||||
<div class="footer clearfix mb-0 text-muted">
|
||||
<div class="float-start">
|
||||
<p>
|
||||
© 2025 <a href="https://www.vshn.ch/en/">VSHN AG</a>, Neugasse 10, CH-8005 Zürich, Switzerland
|
||||
</p>
|
||||
</div>
|
||||
<div class="float-end">
|
||||
<p>
|
||||
Crafted with <span class="text-danger"><i class="bi bi-heart-fill icon-mid"></i></span> in Zurich
|
||||
</p>
|
||||
<div class="container">
|
||||
<div class="footer clearfix mb-0 text-muted">
|
||||
<div class="float-start">
|
||||
<p>
|
||||
© 2025 <a href="https://www.vshn.ch/en/">VSHN AG</a>, Neugasse 10, CH-8005 Zürich, Switzerland
|
||||
</p>
|
||||
</div>
|
||||
<div class="float-end">
|
||||
<p>
|
||||
Crafted with <span class="text-danger"><i class="bi bi-heart-fill icon-mid"></i></span> in Zurich
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
|
143
src/servala/frontend/templates/includes/header.html
Normal file
143
src/servala/frontend/templates/includes/header.html
Normal file
|
@ -0,0 +1,143 @@
|
|||
{% load i18n static %}
|
||||
<header class="mb-5">
|
||||
<div class="header-top">
|
||||
<div class="container">
|
||||
<div class="header-top-left">
|
||||
<div class="logo me-3">
|
||||
<a href="{% if request.organization %}{{ request.organization.urls.base }}{% else %}/{% endif %}">
|
||||
<img id="logo-light"
|
||||
src="{% static 'img/Servala-1.png' %}"
|
||||
alt="{% translate 'Logo' %}">
|
||||
<img id="logo-dark"
|
||||
src="{% static 'img/Servala-2.png' %}"
|
||||
alt="{% translate 'Logo' %}">
|
||||
</a>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
{# request.user.is_authenticated #}
|
||||
{% if user_organizations.count %}
|
||||
<button class="btn btn-outline-primary dropdown-toggle btn-sm"
|
||||
type="button"
|
||||
id="organizationDropdown"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false">
|
||||
{% if request.organization %}
|
||||
{{ request.organization.name }}
|
||||
{% else %}
|
||||
{% translate "Organizations" %}
|
||||
{% endif %}
|
||||
</button>
|
||||
<div class="dropdown-menu shadow"
|
||||
aria-labelledby="organizationDropdown"
|
||||
id="organization-dropdown">
|
||||
{% for organization in user_organizations %}
|
||||
<a class="dropdown-item{% if organization == request.organization %} active{% endif %}"
|
||||
href="{{ organization.urls.base }}">
|
||||
<i class="bi bi-building-fill me-1"></i>
|
||||
{{ organization.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
<a href="{% url 'frontend:organization.create' %}" class="dropdown-item">
|
||||
<i class="bi bi-building-add me-1"></i>
|
||||
<span>{% translate "Create organization" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{% url 'frontend:organization.create' %}"
|
||||
class="btn btn-outline-primary btn-sm">
|
||||
<i class="bi bi-plus-square"></i>
|
||||
<span>{% translate "Create organization" %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="header-top-right">
|
||||
<div class="theme-toggle d-flex gap-2 align-items-center me-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--system-uicons"
|
||||
width="20"
|
||||
height="20"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 21 21">
|
||||
<g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10.5 14.5c2.219 0 4-1.763 4-3.982a4.003 4.003 0 0 0-4-4.018c-2.219 0-4 1.781-4 4c0 2.219 1.781 4 4 4zM4.136 4.136L5.55 5.55m9.9 9.9l1.414 1.414M1.5 10.5h2m14 0h2M4.135 16.863L5.55 15.45m9.899-9.9l1.414-1.415M10.5 19.5v-2m0-14v-2" opacity=".3">
|
||||
</path>
|
||||
<g transform="translate(-210 -1)">
|
||||
<path d="M220.5 2.5v2m6.5.5l-1.5 1.5"></path>
|
||||
<circle cx="220.5" cy="11.5" r="4"></circle>
|
||||
<path d="m214 5l1.5 1.5m5 14v-2m6.5-.5l-1.5-1.5M214 18l1.5-1.5m-4-5h2m14 0h2"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="form-check form-switch fs-6">
|
||||
<input class="form-check-input me-0"
|
||||
type="checkbox"
|
||||
id="toggle-dark"
|
||||
style="cursor: pointer">
|
||||
<label class="form-check-label"></label>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="20"
|
||||
height="20"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="m17.75 4.09l-2.53 1.94l.91 3.06l-2.63-1.81l-2.63 1.81l.91-3.06l-2.53-1.94L12.44 4l1.06-3l1.06 3l3.19.09m3.5 6.91l-1.64 1.25l.59 1.98l-1.7-1.17l-1.7 1.17l.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95l2.06.05m-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85c-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14c.4-.4.82-.76 1.27-1.08c.75-.53 1.93.36 1.85 1.19c-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82c-2.81 3.14-2.7 7.96.31 10.98c3.02 3.01 7.84 3.12 10.98.31Z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
{% if request.user and request.user.is_authenticated %}
|
||||
<div class="dropdown">
|
||||
<a href="#"
|
||||
id="topbarUserDropdown"
|
||||
class="user-dropdown d-flex align-items-center dropend dropdown-toggle"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false">
|
||||
{# <div class="avatar avatar-md2"> #}
|
||||
{# <img src="" alt="Avatar"> #}
|
||||
{# </div>#}
|
||||
<div class="text">
|
||||
<h6 class="user-dropdown-name">{{ request.user }}</h6>
|
||||
{% if request.organization %}<p class="user-dropdown-status text-sm text-muted">{{ request.user_role }}</p>{% endif %}
|
||||
</div>
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end shadow-lg"
|
||||
aria-labelledby="topbarUserDropdown"
|
||||
style="">
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'frontend:profile' %}">{% translate "My Account" %}</a>
|
||||
</li>
|
||||
<li>
|
||||
<hr class="dropdown-divider">
|
||||
</li>
|
||||
<li>
|
||||
<form action="{% url 'frontend:logout' %}"
|
||||
method="post"
|
||||
class="dropdown-item">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class='sidebar-link btn'>{% translate 'Logout' %}</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{% url 'account_login' %}" class="sidebar-link">
|
||||
<i class="bi bi-person-badge-fill"></i>
|
||||
<span>{% translate 'Login' %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="#" class="burger-btn d-block d-xl-none">
|
||||
<i class="bi bi-justify fs-3"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'includes/menu.html' %}
|
||||
</header>
|
39
src/servala/frontend/templates/includes/menu.html
Normal file
39
src/servala/frontend/templates/includes/menu.html
Normal file
|
@ -0,0 +1,39 @@
|
|||
{% load i18n static %}
|
||||
{% if request.user.is_authenticated and request.organization %}
|
||||
<nav class="main-navbar">
|
||||
<div class="container">
|
||||
<ul>
|
||||
<li class="menu-item">
|
||||
<a href="{{ request.organization.urls.base }}" class='menu-link'>
|
||||
<span>
|
||||
<i class="bi bi-grid-fill"></i>
|
||||
{% translate 'Dashboard' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ request.organization.urls.details }}" class='menu-link'>
|
||||
<span>
|
||||
<i class="bi bi-building-gear"></i>
|
||||
{% translate 'Organization' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ request.organization.urls.services }}" class='menu-link'>
|
||||
<span>
|
||||
<i class="bi bi-card-list"></i>
|
||||
{% translate 'Services' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="menu-item">
|
||||
<a href="{{ request.organization.urls.instances }}" class='menu-link'>
|
||||
<span>
|
||||
<i class="bi bi-server"></i>
|
||||
{% translate 'Instances' %}</span>
|
||||
</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
{% endif %}
|
||||
<script src="{% static 'js/sidebar.js' %}" defer></script>
|
|
@ -1,155 +0,0 @@
|
|||
{% load i18n static %}
|
||||
<div id="sidebar">
|
||||
<div id="sidebar">
|
||||
<div class="sidebar-wrapper active">
|
||||
<div class="sidebar-header position-relative">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<div class="logo">
|
||||
<a href="{% if request.organization %}{{ request.organization.urls.base }}{% else %}/{% endif %}">
|
||||
<img src="" alt="{% translate 'Logo' %}" srcset="">
|
||||
</a>
|
||||
</div>
|
||||
<div class="theme-toggle d-flex gap-2 align-items-center mt-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--system-uicons"
|
||||
width="20"
|
||||
height="20"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 21 21">
|
||||
<g fill="none" fill-rule="evenodd" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M10.5 14.5c2.219 0 4-1.763 4-3.982a4.003 4.003 0 0 0-4-4.018c-2.219 0-4 1.781-4 4c0 2.219 1.781 4 4 4zM4.136 4.136L5.55 5.55m9.9 9.9l1.414 1.414M1.5 10.5h2m14 0h2M4.135 16.863L5.55 15.45m9.899-9.9l1.414-1.415M10.5 19.5v-2m0-14v-2" opacity=".3">
|
||||
</path>
|
||||
<g transform="translate(-210 -1)">
|
||||
<path d="M220.5 2.5v2m6.5.5l-1.5 1.5"></path>
|
||||
<circle cx="220.5" cy="11.5" r="4"></circle>
|
||||
<path d="m214 5l1.5 1.5m5 14v-2m6.5-.5l-1.5-1.5M214 18l1.5-1.5m-4-5h2m14 0h2"></path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
<div class="form-check form-switch fs-6">
|
||||
<input class="form-check-input me-0"
|
||||
type="checkbox"
|
||||
id="toggle-dark"
|
||||
style="cursor: pointer">
|
||||
<label class="form-check-label"></label>
|
||||
</div>
|
||||
<svg xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
aria-hidden="true"
|
||||
role="img"
|
||||
class="iconify iconify--mdi"
|
||||
width="20"
|
||||
height="20"
|
||||
preserveAspectRatio="xMidYMid meet"
|
||||
viewBox="0 0 24 24">
|
||||
<path fill="currentColor" d="m17.75 4.09l-2.53 1.94l.91 3.06l-2.63-1.81l-2.63 1.81l.91-3.06l-2.53-1.94L12.44 4l1.06-3l1.06 3l3.19.09m3.5 6.91l-1.64 1.25l.59 1.98l-1.7-1.17l-1.7 1.17l.59-1.98L15.75 11l2.06-.05L18.5 9l.69 1.95l2.06.05m-2.28 4.95c.83-.08 1.72 1.1 1.19 1.85c-.32.45-.66.87-1.08 1.27C15.17 23 8.84 23 4.94 19.07c-3.91-3.9-3.91-10.24 0-14.14c.4-.4.82-.76 1.27-1.08c.75-.53 1.93.36 1.85 1.19c-.27 2.86.69 5.83 2.89 8.02a9.96 9.96 0 0 0 8.02 2.89m-1.64 2.02a12.08 12.08 0 0 1-7.8-3.47c-2.17-2.19-3.33-5-3.49-7.82c-2.81 3.14-2.7 7.96.31 10.98c3.02 3.01 7.84 3.12 10.98.31Z">
|
||||
</path>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="sidebar-toggler x">
|
||||
<a href="#" class="sidebar-hide d-xl-none d-block"><i class="bi bi-x bi-middle"></i></a>
|
||||
</div>
|
||||
</div>
|
||||
{% if request.user.is_authenticated %}
|
||||
{# request.user.is_authenticated #}
|
||||
{% if user_organizations.count %}
|
||||
<button class="btn btn-outline-primary dropdown-toggle w-100"
|
||||
type="button"
|
||||
id="organizationDropdown"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-haspopup="true"
|
||||
aria-expanded="false">
|
||||
{% if request.organization %}
|
||||
{{ request.organization.name }}
|
||||
{% else %}
|
||||
{% translate "Organizations" %}
|
||||
{% endif %}
|
||||
</button>
|
||||
<div class="dropdown-menu shadow"
|
||||
aria-labelledby="organizationDropdown"
|
||||
id="organization-dropdown">
|
||||
{% for organization in user_organizations %}
|
||||
<a class="dropdown-item{% if organization == request.organization %} active{% endif %}"
|
||||
href="{{ organization.urls.base }}">
|
||||
<i class="bi bi-building-fill me-1"></i>
|
||||
{{ organization.name }}
|
||||
</a>
|
||||
{% endfor %}
|
||||
<a href="{% url 'frontend:organization.create' %}" class="dropdown-item">
|
||||
<i class="bi bi-building-add me-1"></i>
|
||||
<span>{% translate "Create organization" %}</span>
|
||||
</a>
|
||||
</div>
|
||||
{% else %}
|
||||
<a href="{% url 'frontend:organization.create' %}"
|
||||
class="btn btn-outline-primary w-100">
|
||||
<i class="bi bi-plus-square"></i>
|
||||
<span>{% translate "Create organization" %}</span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="sidebar-menu">
|
||||
<ul class="menu">
|
||||
{% if not request.user.is_authenticated %}
|
||||
<li class="sidebar-item">
|
||||
<a href="{% url 'account_login' %}" class="sidebar-link">
|
||||
<i class="bi bi-person-badge-fill"></i>
|
||||
<span>{% translate 'Login' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% else %}
|
||||
{% if request.organization %}
|
||||
<li class="sidebar-item">
|
||||
<a href="{{ request.organization.urls.base }}" class='sidebar-link'>
|
||||
<i class="bi bi-grid-fill"></i>
|
||||
<span>{% translate 'Dashboard' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-title">{% translate 'Organization' %}</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="{{ request.organization.urls.details }}" class='sidebar-link'>
|
||||
<i class="bi bi-building-gear"></i>
|
||||
<span>{% translate 'Details' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-title">{% translate 'Services' %}</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="{{ request.organization.urls.services }}" class='sidebar-link'>
|
||||
<i class="bi bi-card-list"></i>
|
||||
<span>{% translate 'Available Services' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="{{ request.organization.urls.instances }}" class='sidebar-link'>
|
||||
<i class="bi bi-server"></i>
|
||||
<span>{% translate 'Instances' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="sidebar-title">{% translate 'Account' %}</li>
|
||||
<li class="sidebar-item">
|
||||
<a href="{% url 'frontend:profile' %}" class='sidebar-link'>
|
||||
<i class="bi bi-file-person"></i>
|
||||
<span>{% translate 'Profile' %}</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-item">
|
||||
<form action="{% url 'frontend:logout' %}" method="post">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class='sidebar-link btn'>
|
||||
<i class="bi bi-box-arrow-right"></i>
|
||||
<span>{% translate 'Log out' %}</span>
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
{% endif %}
|
||||
{# request.user.is_authenticated #}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="{% static 'js/sidebar.js' %}" defer></script>
|
Loading…
Add table
Add a link
Reference in a new issue