Merge pull request 'First branding integration' (#40) from 20-styling-branding into main
All checks were successful
Build and Deploy Staging / build (push) Successful in 56s
Tests / test (push) Successful in 23s
Build and Deploy Staging / deploy (push) Successful in 7s

Reviewed-on: #40
This commit is contained in:
Tobias Kunze 2025-04-07 21:29:44 +00:00
commit d53804b8d0
11 changed files with 315 additions and 218 deletions

View file

@ -16,10 +16,10 @@
{% csrf_token %}
{{ redirect_field }}
<button href="{{ href }}"
class="btn btn-warning btn-lg icon icon-left"
class="btn btn-warning btn-lg icon icon-left btn-keycloak"
title="{{ provider.name }}">
<img src="{% static 'img/keycloak.svg' %}" style="height: 30px">
<span class="mx-1">{% translate "Sign in with your" %} {{ provider.name }}</span>
<span class="ms-2">{% translate "Sign In" %}</span>
</button>
</form>
{% endfor %}

View file

@ -1,4 +1,4 @@
{% load static %}
{% load i18n static %}
<!DOCTYPE html>
<html lang="en">
<head>
@ -20,13 +20,9 @@
<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 id="main" class="layout-horizontal">
{% include 'includes/header.html' %}
<div class="content-wrapper container">
<div class="page-heading">
<h3>
{% block page_title %}
@ -52,7 +48,9 @@
</section>
{% endblock content %}
</div>
</div>
<footer>
<div class="container">
<div class="footer clearfix mb-0 text-muted">
<div class="float-start">
<p>
@ -65,6 +63,7 @@
</p>
</div>
</div>
</div>
</footer>
</div>
</div>

View file

@ -115,10 +115,11 @@
You are logged in with your VSHN user account. Change your password and other account data here:
{% endblocktranslate %}
</p>
<div>
<a href="{{ account_href }}"
class="btn btn-warning btn-lg icon icon-left">
class="btn btn-warning btn-lg icon icon-left btn-keycloak">
<img src="{% static 'img/keycloak.svg' %}" style="height: 30px">
<span class="mx-1">{% translate "VSHN Account" %}</span>
<span class="mx-1">{% translate "Account" %}</span>
</a>
</div>
</div>
@ -126,4 +127,4 @@
</div>
</div>
</section>
{% endblock content %}
{% endblock content %}

View 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>

View 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>

View file

@ -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>

View file

@ -1,3 +1,55 @@
:root, html[data-bs-theme="dark"]:root {
--bs-primary: #9A63EC;
--bs-link-color: var(--bs-primary);
--bs-link-color-rgb: 154, 99, 236;
--bs-link-hover-color-rgb: 154, 99, 236;
--brand-black: #333333;
--brand-mid: #C4ACE0;
--brand-light: #FCEAFF;
--brand-success: #64BAAA;
}
.dropdown-menu, html[data-bs-theme="dark"] .dropdown-menu {
--bs-dropdown-link-active-bg: var(--bs-primary);
}
.layout-horizontal .main-navbar {
background-color: var(--bs-primary);
}
html[data-bs-theme="dark"] .btn-primary, .btn-primary {
--bs-btn-bg: var(--bs-primary);
--bs-btn-border-color: var(--bs-primary);
--bs-btn-hover-bg: var(--bs-primary);
--bs-btn-hover-border-color: var(--bs-primary);
--bs-btn-active-bg: var(--bs-primary);
--bs-btn-active-border-color: var(--bs-primary);
--bs-btn-disabled-bg: var(--bs-primary);
--bs-btn-disabled-border-color: var(--bs-primary);
}
.btn.btn-light-primary {
background-color: var(--brand-light);
color: var(--bs-primary);
}
html[data-bs-theme="dark"] .btn.btn-light-primary {
background-color: var(--brand-light);
}
html[data-bs-theme="dark"] .btn-outline-primary, .btn-outline-primary {
--bs-btn-color: var(--bs-primary);
--bs-btn-border-color: var(--bs-primary);
--bs-btn-hover-bg: var(--bs-primary);
--bs-hover-border-color: var(--bs-primary);
--bs-btn-active-bg: var(--bs-primary);
--bs-btn-active-border-color: var(--bs-primary);
--bs-btn-disabled-color: var(--bs-primary);
--bs-btn-disabled-color: var(--bs-primary);
--bs-btn-disabled-border-color: var(--bs-primary);
}
.header-top-left {
display: flex;
align-items: baseline;
}
#main .header-top .logo img {
height: 32px;
}
.form-group.d-inline {
margin-bottom: 0;
}
@ -9,3 +61,27 @@
flex-grow: 1;
}
}
[data-bs-theme="light"] {
header #logo-dark {
display: none;
}
header #logo-light {
display: inline-block;
}
}
[data-bs-theme="dark"] {
header #logo-light {
display: none;
}
header #logo-dark {
display: inline-block;
}
}
.btn-keycloak {
display: flex;
align-items: center;
}
a.btn-keycloak {
display: inline-flex;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View file

@ -1,6 +1 @@
<svg width="107" height="60" fill="none" xmlns="http://www.w3.org/2000/svg" class="image" aria-hidden="true">
<circle cx="53.002" cy="30" r="19" fill="#4CC3FF"></circle>
<path opacity="0.25" d="M67.833 41.874A18.92 18.92 0 0071.999 30c0-10.493-8.506-19-19-19a18.932 18.932 0 00-12.868 5.021c14.446.554 26.182 11.675 27.702 25.853z" fill="#000D1A"></path>
<path d="M31.594 6.491v8.571l5.217-3.173a31.165 31.165 0 0132.426 0l.622.378v.006l.14.078v-8.39l-.137-.07a38.382 38.382 0 00-36.807 1.712l-1.461.888zM74.436 53.508v-8.57l-5.218 3.173a31.165 31.165 0 01-32.425 0l-.625-.38v-.005L36 47.64v8.39l.168.079a38.382 38.382 0 0036.807-1.712l1.461-.889z" fill="#4CC3FF"></path>
<path d="M31.571 15.063v-8.57L0 25.694v8.614L31.571 53.51v-8.57L7.011 30l24.56-14.938zM74.432 53.511l31.571-19.202v-8.614L74.432 6.492v8.571l24.56 14.939-24.56 14.938v8.571z" fill="#000D1A"></path>
</svg>
<svg id="Ebene_1" data-name="Ebene 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1271.63 301.28"><defs><style>.cls-1{fill:#444;}.cls-2{fill:#4081cb;}</style></defs><polyline class="cls-1" points="164.16 264.17 0 169.29 0 128.63 163.16 33.24 162.55 75.49 34.64 149.71 164.34 222.5 164.16 264.17"/><path class="cls-2" d="M469.84,75.53v38.41s-40.79-30-90.18-30C326.23,83.89,266.52,123,266.52,123V80.84c41.3-22.09,77.94-33.31,113.59-33.31,43.55,0,89.73,28,89.73,28" transform="translate(-103.97 -47.53)"/><path class="cls-2" d="M381,295.1A99.55,99.55,0,1,0,381,96c-55.12,0-99.81,44.57-99.81,99.54A99.68,99.68,0,0,0,381,295.1" transform="translate(-103.97 -47.53)"/><polyline class="cls-1" points="389.91 36.82 554.07 131.7 554.07 172.36 390.91 267.75 391.51 225.5 519.43 151.28 389.73 78.49 389.91 36.82"/><path class="cls-2" d="M292.1,320.8V282.39s40.8,30.05,90.19,30.05c53.43,0,113.13-39.13,113.13-39.13v42.18c-41.29,22.09-77.94,33.31-113.58,33.31-43.55,0-89.74-28-89.74-28" transform="translate(-103.97 -47.53)"/><path class="cls-1" d="M727.16,119.64h44.32l39.38,114.07,39.6-114.07h42.3L831.11,277.37H788.36Z" transform="translate(-103.97 -47.53)"/><path class="cls-1" d="M989.39,155q-14.28-4.72-24-4.73-7.65,0-12,2.81a9.17,9.17,0,0,0-4.38,8.22,11.24,11.24,0,0,0,3.82,8.66,29.27,29.27,0,0,0,9.45,5.62q5.63,2.14,16.65,5.52a216.24,216.24,0,0,1,27.11,9.45A47.34,47.34,0,0,1,1024.38,205q7.65,9.78,7.65,25.54t-8.32,26.88q-8.33,11.15-22.84,16.76a88.72,88.72,0,0,1-32.29,5.63,116.87,116.87,0,0,1-39-6.86,107,107,0,0,1-33.63-18.79l16-32.17a99.35,99.35,0,0,0,28.24,17.32q16.3,6.75,28.91,6.75,9.22,0,14.51-3.38a11,11,0,0,0,5.29-9.89,11.66,11.66,0,0,0-3.94-9,28.76,28.76,0,0,0-9.9-5.74q-6-2.15-16.76-5.06a205.9,205.9,0,0,1-26.77-9.12,47.28,47.28,0,0,1-18.12-14q-7.53-9.33-7.53-24.86a43.39,43.39,0,0,1,7.76-25.65q7.75-11,22-17t33.19-6a120.31,120.31,0,0,1,33.75,4.84,111.4,111.4,0,0,1,29.25,12.94l-15.53,32.85A138.22,138.22,0,0,0,989.39,155Z" transform="translate(-103.97 -47.53)"/><path class="cls-1" d="M1053,119.64h41.17V184h63.68V119.64H1199V277.37h-41.17V216.84h-63.68v60.53H1053Z" transform="translate(-103.97 -47.53)"/><path class="cls-1" d="M1337.35,119.64h38.25V277.37h-36l-71.55-94.28v94.28h-38.47V119.64h36.22l71.78,95Z" transform="translate(-103.97 -47.53)"/></svg>

Before

Width:  |  Height:  |  Size: 893 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Before After
Before After

View file

@ -1,13 +1,12 @@
/**
* This script marks the current path as active in the sidebar.
* This script marks the current path as active in the menu.
*/
const markActive = (link) => {
const parentItem = link.closest('.sidebar-item');
const parentItem = link.closest('.menu-item');
link.classList.add('active');
if (parentItem) {
parentItem.classList.add('active');
} else {
link.classList.add('active');
}
}
@ -16,13 +15,13 @@ const checkLink = (fuzzy) => {
document.addEventListener('DOMContentLoaded', () => {
const currentPath = window.location.pathname;
const sidebarLinks = [...document.querySelectorAll('a.sidebar-link')]
const menuLinks = [...document.querySelectorAll('a.menu-link')]
const exactMatches = sidebarLinks.filter(link => link.getAttribute('href') === currentPath)
const exactMatches = menuLinks.filter(link => link.getAttribute('href') === currentPath)
if (exactMatches.length > 0) {
markActive(exactMatches[0])
} else {
fuzzyMatches = sidebarLinks.filter(link => currentPath.startsWith(link.getAttribute('href')))
fuzzyMatches = menuLinks.filter(link => currentPath.startsWith(link.getAttribute('href')))
if (fuzzyMatches.length > 0) {
const longestMatch = fuzzyMatches.sort((a, b) => b.href.length - a.href.length)[0]
markActive(longestMatch)