mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-22 20:12:00 -06:00
#6372: Implement layout improvements
This commit is contained in:
parent
a8a9e061a1
commit
eb0d5c996e
@ -1,4 +1,4 @@
|
||||
// Entry for all 3rd party library imports that do not rely on Bootstrap or NetBox styles.
|
||||
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800&display=swap');
|
||||
@import '@mdi/font/css/materialdesignicons.min.css';
|
||||
@import 'flatpickr/dist/flatpickr.css';
|
||||
|
BIN
netbox/project-static/dist/netbox-dark.css
vendored
BIN
netbox/project-static/dist/netbox-dark.css
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
netbox/project-static/dist/netbox-external.css
vendored
BIN
netbox/project-static/dist/netbox-external.css
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
netbox/project-static/dist/netbox-light.css
vendored
BIN
netbox/project-static/dist/netbox-light.css
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
BIN
netbox/project-static/dist/netbox.js
vendored
BIN
netbox/project-static/dist/netbox.js
vendored
Binary file not shown.
BIN
netbox/project-static/dist/netbox.js.map
vendored
BIN
netbox/project-static/dist/netbox.js.map
vendored
Binary file not shown.
BIN
netbox/project-static/dist/rack_elevation.css
vendored
BIN
netbox/project-static/dist/rack_elevation.css
vendored
Binary file not shown.
File diff suppressed because one or more lines are too long
@ -98,6 +98,21 @@ table td > .progress {
|
||||
min-width: 6rem;
|
||||
}
|
||||
|
||||
span.profile-button .dropdown-menu {
|
||||
transition: opacity 0.2s ease-in-out;
|
||||
display: block !important;
|
||||
right: 0;
|
||||
left: auto;
|
||||
margin-top: 0.5rem;
|
||||
box-shadow: $box-shadow;
|
||||
&:not(.show) {
|
||||
opacity: 0;
|
||||
}
|
||||
&.show {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
div#advanced-search-content div.card div.card-body div.col:not(:last-child) {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
@ -362,6 +377,12 @@ div.content-container {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-left: $sidebar-width;
|
||||
}
|
||||
|
||||
div.content {
|
||||
flex: 1;
|
||||
}
|
||||
@ -383,27 +404,36 @@ div.content-container {
|
||||
z-index: 100; /* Behind the navbar */
|
||||
border-right: 1px solid $border-color;
|
||||
background-color: var(--nbx-sidebar-bg);
|
||||
max-height: 100%;
|
||||
width: 100%;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
width: 100%;
|
||||
max-width: $sidebar-width;
|
||||
}
|
||||
|
||||
@media (max-width: map.get($grid-breakpoints, 'md')) {
|
||||
top: 8.125rem;
|
||||
}
|
||||
|
||||
div.accordion-item {
|
||||
div.accordion-collapse {
|
||||
&.collapse.show,
|
||||
&.collapsing {
|
||||
background-color: $accordion-body-active-bg;
|
||||
}
|
||||
}
|
||||
& > a.accordion-button.nav-link {
|
||||
&:hover {
|
||||
color: $accordion-button-active-color;
|
||||
background-color: $accordion-button-active-bg;
|
||||
}
|
||||
&:focus {
|
||||
border-color: unset;
|
||||
border: unset;
|
||||
|
||||
& > a.accordion-button {
|
||||
&:not(.collapsed) {
|
||||
box-shadow: unset;
|
||||
}
|
||||
&.nav-link {
|
||||
border-radius: $border-radius;
|
||||
&:hover {
|
||||
color: $accordion-button-active-color;
|
||||
background-color: $accordion-button-active-bg;
|
||||
}
|
||||
&:focus {
|
||||
border-color: unset;
|
||||
box-shadow: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
"parcel-bundler": "1.12.3",
|
||||
"query-string": "^6.14.1",
|
||||
"sass": "^1.32.8",
|
||||
"simplebar": "^5.3.4",
|
||||
"slim-select": "^1.27.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -1,8 +1,5 @@
|
||||
import { getElements, isTruthy } from './util';
|
||||
|
||||
type ColorMode = 'light' | 'dark';
|
||||
type ColorModePreference = ColorMode | 'none';
|
||||
|
||||
const COLOR_MODE_KEY = 'netbox-color-mode';
|
||||
const TEXT_WHEN_DARK = 'Light Mode';
|
||||
const TEXT_WHEN_LIGHT = 'Dark Mode';
|
||||
|
11
netbox/project-static/src/global.d.ts
vendored
11
netbox/project-static/src/global.d.ts
vendored
@ -169,3 +169,14 @@ interface ObjectWithGroup extends APIObjectBase {
|
||||
declare const messages: string[];
|
||||
|
||||
type FormControls = HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
|
||||
|
||||
type ColorMode = 'light' | 'dark';
|
||||
type ColorModePreference = ColorMode | 'none';
|
||||
type ConfigContextFormat = 'json' | 'yaml';
|
||||
|
||||
type UserPreferences = {
|
||||
ui: {
|
||||
colorMode: ColorMode;
|
||||
showRackImages: boolean;
|
||||
};
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import 'babel-polyfill';
|
||||
import '@popperjs/core';
|
||||
import 'bootstrap';
|
||||
import 'simplebar';
|
||||
import './netbox';
|
||||
|
@ -9,6 +9,7 @@ import { initClipboard } from './clipboard';
|
||||
import { initDateSelector } from './dateSelector';
|
||||
import { initTableConfig } from './tableConfig';
|
||||
import { initInterfaceTable } from './tables';
|
||||
import { initSideNav } from './sidenav';
|
||||
|
||||
function init() {
|
||||
for (const init of [
|
||||
@ -23,6 +24,7 @@ function init() {
|
||||
initClipboard,
|
||||
initTableConfig,
|
||||
initInterfaceTable,
|
||||
initSideNav,
|
||||
]) {
|
||||
init();
|
||||
}
|
||||
|
22
netbox/project-static/src/sidenav.ts
Normal file
22
netbox/project-static/src/sidenav.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { getElement, getElements } from './util';
|
||||
|
||||
const breakpoints = {
|
||||
sm: 540,
|
||||
md: 720,
|
||||
lg: 960,
|
||||
xl: 1140,
|
||||
};
|
||||
|
||||
function toggleBodyPosition(position: HTMLBodyElement['style']['position']): void {
|
||||
for (const element of getElements('body')) {
|
||||
element.style.position = position;
|
||||
}
|
||||
}
|
||||
|
||||
export function initSideNav() {
|
||||
const element = getElement<HTMLAnchorElement>('sidebarMenu');
|
||||
if (element !== null && document.body.clientWidth < breakpoints.lg) {
|
||||
element.addEventListener('shown.bs.collapse', () => toggleBodyPosition('fixed'));
|
||||
element.addEventListener('hidden.bs.collapse', () => toggleBodyPosition('relative'));
|
||||
}
|
||||
}
|
@ -235,11 +235,13 @@ $theme-color-addons: (
|
||||
'pink-900': $pink-900,
|
||||
);
|
||||
|
||||
$font-family-sans-serif: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI',
|
||||
Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji',
|
||||
'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
$font-family-sans-serif: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||
'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji',
|
||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||
$font-family-monospace: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono',
|
||||
'Courier New', monospace;
|
||||
|
||||
$accordion-padding-y: 0.8125rem;
|
||||
$accordion-padding-x: 0.8125rem;
|
||||
|
||||
$sidebar-width: 280px;
|
||||
|
@ -1070,6 +1070,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@iarna/toml/-/toml-2.2.5.tgz#b32366c89b43c6f8cefbdefac778b9c828e3ba8c"
|
||||
integrity sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==
|
||||
|
||||
"@juggle/resize-observer@^3.3.1":
|
||||
version "3.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@juggle/resize-observer/-/resize-observer-3.3.1.tgz#b50a781709c81e10701004214340f25475a171a0"
|
||||
integrity sha512-zMM9Ds+SawiUkakS7y94Ymqx+S0ORzpG3frZirN3l+UlXUmSUR7hF4wxCVqW+ei94JzV5kt0uXBcoOEAuiydrw==
|
||||
|
||||
"@mdi/font@^5.9.55":
|
||||
version "5.9.55"
|
||||
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-5.9.55.tgz#41acd50b88073ded7095fc3029d8712b6e12f38e"
|
||||
@ -2022,6 +2027,11 @@ camelcase@^5.0.0:
|
||||
resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320"
|
||||
integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==
|
||||
|
||||
can-use-dom@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/can-use-dom/-/can-use-dom-0.1.0.tgz#22cc4a34a0abc43950f42c6411024a3f6366b45a"
|
||||
integrity sha1-IsxKNKCrxDlQ9CxkEQJKP2NmtFo=
|
||||
|
||||
caniuse-api@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0"
|
||||
@ -2388,6 +2398,11 @@ core-js@^2.4.0, core-js@^2.5.0:
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec"
|
||||
integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==
|
||||
|
||||
core-js@^3.0.1:
|
||||
version "3.15.1"
|
||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.15.1.tgz#6c08ab88abdf56545045ccf5fd81f47f407e7f1a"
|
||||
integrity sha512-h8VbZYnc9pDzueiS2610IULDkpFFPunHwIpl8yRwFahAEEdSpHlTy3h3z3rKq5h11CaUdBEeRViu9AYvbxiMeg==
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
@ -4820,6 +4835,11 @@ lodash.sortby@^4.7.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438"
|
||||
integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=
|
||||
|
||||
lodash.throttle@^4.1.1:
|
||||
version "4.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4"
|
||||
integrity sha1-wj6RtxAkKscMN/HhzaknTMOb8vQ=
|
||||
|
||||
lodash.toarray@^4.4.0:
|
||||
version "4.4.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561"
|
||||
@ -6957,6 +6977,18 @@ simple-swizzle@^0.2.2:
|
||||
dependencies:
|
||||
is-arrayish "^0.3.1"
|
||||
|
||||
simplebar@^5.3.4:
|
||||
version "5.3.4"
|
||||
resolved "https://registry.yarnpkg.com/simplebar/-/simplebar-5.3.4.tgz#7de8d4a07ed3c6612644f4dbc04a8427fdf038ef"
|
||||
integrity sha512-2mCaVdiroCKmXuD+Qfy+QSE32m5BMuZ4ssHvRD1QEPYH95Re/kox7j/Wy0Hje8Uo7LY7O6JK3XSNJmesGlsP8Q==
|
||||
dependencies:
|
||||
"@juggle/resize-observer" "^3.3.1"
|
||||
can-use-dom "^0.1.0"
|
||||
core-js "^3.0.1"
|
||||
lodash.debounce "^4.0.8"
|
||||
lodash.memoize "^4.1.2"
|
||||
lodash.throttle "^4.1.1"
|
||||
|
||||
slash@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
|
||||
|
@ -6,126 +6,123 @@
|
||||
|
||||
{% block layout %}
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<main class="col-md-9 ms-sm-auto col-lg-10 px-0">
|
||||
<main class="ms-sm-auto px-0">
|
||||
{# Sidebar #}
|
||||
<nav id="sidebar-menu" class="d-md-block sidebar collapse px-0" data-simplebar>
|
||||
|
||||
{# Sidebar #}
|
||||
<nav id="sidebar-menu" class="col-md-3 col-lg-2 d-md-block sidebar collapse px-0">
|
||||
{# Sidebar content #}
|
||||
<div class="position-sticky pt-3">
|
||||
|
||||
{# Sidebar content #}
|
||||
<div class="position-sticky pt-3">
|
||||
|
||||
{# Logo #}
|
||||
<a class="p-1 sidebar-logo d-none d-md-flex justify-content-center" href="{% url 'home' %}">
|
||||
<img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" />
|
||||
</a>
|
||||
|
||||
{# Search bar #}
|
||||
<ul class="nav flex-column">
|
||||
<div class="d-block d-md-none mx-1 my-3 search-container">
|
||||
{% search_options %}
|
||||
</div>
|
||||
<div class="d-flex d-md-none mx-1 my-3 justify-content-end">
|
||||
{% include 'inc/profile_button.html' %}
|
||||
</div>
|
||||
{% nav %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
{# Sidebar footer #}
|
||||
<div class="d-flex flex-column container-fluid mt-auto justify-content-end sidebar-bottom">
|
||||
<nav class="nav justify-content-between mb-2 mt-4 px-2">
|
||||
|
||||
{# Documentation #}
|
||||
<a type="button" target="_blank" class="nav-link" href="https://netbox.readthedocs.io/">
|
||||
<i title="Docs" class="mdi mdi-book-open-variant text-primary" data-bs-placement="top" data-bs-toggle="tooltip"></i>
|
||||
</a>
|
||||
|
||||
{# API docs #}
|
||||
<a class="nav-link" href="{% url 'api_docs' %}" target="_blank">
|
||||
<i title="API" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-braces text-primary"></i>
|
||||
</a>
|
||||
|
||||
{# GitHub #}
|
||||
<a class="nav-link" href="https://github.com/netbox-community/netbox" target="_blank">
|
||||
<i title="Source Code" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-tags text-primary"></i>
|
||||
</a>
|
||||
|
||||
{# GitHub wiki #}
|
||||
<a target="_blank" class="nav-link" href="https://github.com/netbox-community/netbox/wiki">
|
||||
<i title="Get Help" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-lifebuoy text-primary"></i>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
{# Body #}
|
||||
<div class="content-container">
|
||||
|
||||
{# Top bar #}
|
||||
<nav class="navbar navbar-light sticky-top flex-md-nowrap p-3 search container-fluid">
|
||||
<div class="d-md-none w-100 d-flex justify-content-between align-items-center my-3">
|
||||
<a class="px-2 sidebar-logo d-block d-md-none" href="{% url 'home' %}">
|
||||
<img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" />
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded="false"
|
||||
data-bs-toggle="collapse"
|
||||
aria-controls="sidebar-menu"
|
||||
data-bs-target="#sidebar-menu"
|
||||
aria-label="Toggle Navigation"
|
||||
class="navbar-toggler position-relative collapsed"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="d-none d-md-flex w-100 search-container">
|
||||
{% search_options %}
|
||||
{% include 'inc/profile_button.html' %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{# Page header #}
|
||||
{% block header %}
|
||||
<div class="title-container px-3 py-3">
|
||||
|
||||
{# Title #}
|
||||
<div id="content-title">
|
||||
{# Center-align title in object-edit views #}
|
||||
<h1 class="h2 w-100{% if form or vc_form %} text-center{% endif %}">{% block title %}{% endblock title %}</h1>
|
||||
</div>
|
||||
|
||||
{# Controls #}
|
||||
{% block controls %}{% endblock controls %}
|
||||
{# Logo #}
|
||||
<a class="p-1 sidebar-logo d-none d-md-flex justify-content-center" href="{% url 'home' %}">
|
||||
<img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" />
|
||||
</a>
|
||||
|
||||
{# Search bar #}
|
||||
<ul class="nav flex-column px-4">
|
||||
<div class="d-block d-md-none mx-1 my-3 search-container">
|
||||
{% search_options %}
|
||||
</div>
|
||||
{% endblock header %}
|
||||
|
||||
{# Page content #}
|
||||
<div id="content" class="container-fluid content px-0 m-0">
|
||||
{% block tabs %}{% endblock %}
|
||||
<div class="px-3">
|
||||
{% block content %}{% endblock %}
|
||||
<div class="d-flex d-md-none mx-1 my-3 justify-content-end">
|
||||
{% include 'inc/profile_button.html' %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Page footer #}
|
||||
<footer class="footer container-fluid pb-3 pt-4 px-0">
|
||||
<div class="row align-items-center justify-content-end mx-0">
|
||||
<div class="col-auto d-none d-md-block"></div>
|
||||
<div class="col text-center small text-muted">
|
||||
<span class="fw-light d-block d-md-inline">{% now 'Y-m-d H:i:s T' %}</span>
|
||||
<span class="ms-md-3 d-block d-md-inline">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
{% nav %}
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
{# Sidebar footer #}
|
||||
<div class="d-flex flex-column container-fluid mt-auto justify-content-end sidebar-bottom">
|
||||
<nav class="nav justify-content-between mb-2 mt-4 px-2">
|
||||
|
||||
{# Documentation #}
|
||||
<a type="button" target="_blank" class="nav-link" href="https://netbox.readthedocs.io/">
|
||||
<i title="Docs" class="mdi mdi-book-open-variant text-primary" data-bs-placement="top" data-bs-toggle="tooltip"></i>
|
||||
</a>
|
||||
|
||||
{# API docs #}
|
||||
<a class="nav-link" href="{% url 'api_docs' %}" target="_blank">
|
||||
<i title="API" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-braces text-primary"></i>
|
||||
</a>
|
||||
|
||||
{# GitHub #}
|
||||
<a class="nav-link" href="https://github.com/netbox-community/netbox" target="_blank">
|
||||
<i title="Source Code" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-code-tags text-primary"></i>
|
||||
</a>
|
||||
|
||||
{# GitHub wiki #}
|
||||
<a target="_blank" class="nav-link" href="https://github.com/netbox-community/netbox/wiki">
|
||||
<i title="Get Help" data-bs-placement="top" data-bs-toggle="tooltip" class="mdi mdi-lifebuoy text-primary"></i>
|
||||
</a>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
</nav>
|
||||
|
||||
{# Body #}
|
||||
<div class="content-container">
|
||||
|
||||
{# Top bar #}
|
||||
<nav class="navbar navbar-light sticky-top flex-md-nowrap p-3 search container-fluid">
|
||||
<div class="d-md-none w-100 d-flex justify-content-between align-items-center my-3">
|
||||
<a class="px-2 sidebar-logo d-block d-md-none" href="{% url 'home' %}">
|
||||
<img src="{% static 'netbox_logo.svg' %}" alt="NetBox logo" />
|
||||
</a>
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded="false"
|
||||
data-bs-toggle="collapse"
|
||||
aria-controls="sidebar-menu"
|
||||
data-bs-target="#sidebar-menu"
|
||||
aria-label="Toggle Navigation"
|
||||
class="navbar-toggler position-relative collapsed"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="d-none d-md-flex w-100 search-container">
|
||||
{% search_options %}
|
||||
{% include 'inc/profile_button.html' %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{# Page header #}
|
||||
{% block header %}
|
||||
<div class="title-container px-3 py-3">
|
||||
|
||||
{# Title #}
|
||||
<div id="content-title">
|
||||
{# Center-align title in object-edit views #}
|
||||
<h1 class="h2 w-100{% if form or vc_form %} text-center{% endif %}">{% block title %}{% endblock title %}</h1>
|
||||
</div>
|
||||
|
||||
{# Controls #}
|
||||
{% block controls %}{% endblock controls %}
|
||||
|
||||
</div>
|
||||
{% endblock header %}
|
||||
|
||||
{# Page content #}
|
||||
<div id="content" class="container-fluid content px-0 m-0">
|
||||
{% block tabs %}{% endblock %}
|
||||
<div class="px-3">
|
||||
{% block content %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{# Page footer #}
|
||||
<footer class="footer container-fluid pb-3 pt-4 px-0">
|
||||
<div class="row align-items-center justify-content-end mx-0">
|
||||
<div class="col-auto d-none d-md-block"></div>
|
||||
<div class="col text-center small text-muted">
|
||||
<span class="fw-light d-block d-md-inline">{% now 'Y-m-d H:i:s T' %}</span>
|
||||
<span class="ms-md-3 d-block d-md-inline">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</span>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
|
||||
</main>
|
||||
</div>
|
||||
{% endblock layout %}
|
||||
|
@ -1,5 +1,5 @@
|
||||
{% if request.user.is_authenticated %}
|
||||
<span class="dropdown ms-0 ms-md-3">
|
||||
<span class="dropdown ms-0 ms-md-3 profile-button">
|
||||
<button
|
||||
type="button"
|
||||
aria-expanded="false"
|
||||
@ -25,12 +25,12 @@
|
||||
</li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'user:profile' %}">
|
||||
<i class="mdi mdi-account"></i> Profile
|
||||
<i class="mdi mdi-account"></i> Profile & Settings
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider" /></li>
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'logout' %}">
|
||||
<a class="dropdown-item text-danger" href="{% url 'logout' %}">
|
||||
<i class="mdi mdi-logout-variant"></i> Log Out
|
||||
</a>
|
||||
</li>
|
||||
|
@ -11,6 +11,7 @@
|
||||
data-bs-target="#{{ menu.label|lower }}"
|
||||
class="d-flex justify-content-between align-items-center accordion-button nav-link collapsed">
|
||||
<span class="fw-bold sidebar-nav-link">
|
||||
<i class="mdi mdi-{{ menu.icon }} me-1"></i>
|
||||
{{ menu.label }}
|
||||
</span>
|
||||
</a>
|
||||
|
@ -33,11 +33,13 @@ class Menu:
|
||||
"""A top level menu group. Example: Organization, Devices, IPAM."""
|
||||
|
||||
label: str
|
||||
icon: str
|
||||
groups: Sequence[MenuGroup]
|
||||
|
||||
|
||||
ORGANIZATION_MENU = Menu(
|
||||
label="Organization",
|
||||
icon="domain",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="Sites",
|
||||
@ -83,6 +85,7 @@ ORGANIZATION_MENU = Menu(
|
||||
|
||||
DEVICES_MENU = Menu(
|
||||
label="Devices",
|
||||
icon="server",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="Devices",
|
||||
@ -150,6 +153,7 @@ DEVICES_MENU = Menu(
|
||||
|
||||
IPAM_MENU = Menu(
|
||||
label="IPAM",
|
||||
icon="counter",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="IP Addresses",
|
||||
@ -204,6 +208,7 @@ IPAM_MENU = Menu(
|
||||
|
||||
VIRTUALIZATION_MENU = Menu(
|
||||
label="Virtualization",
|
||||
icon="monitor",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="Virtual Machines",
|
||||
@ -231,6 +236,7 @@ VIRTUALIZATION_MENU = Menu(
|
||||
|
||||
CIRCUITS_MENU = Menu(
|
||||
label="Circuits",
|
||||
icon="transit-connection-variant",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="Circuits",
|
||||
@ -256,6 +262,7 @@ CIRCUITS_MENU = Menu(
|
||||
|
||||
POWER_MENU = Menu(
|
||||
label="Power",
|
||||
icon="flash",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="Power",
|
||||
@ -271,6 +278,7 @@ POWER_MENU = Menu(
|
||||
|
||||
OTHER_MENU = Menu(
|
||||
label="Other",
|
||||
icon="notification-clear-all",
|
||||
groups=(
|
||||
MenuGroup(
|
||||
label="Logging",
|
||||
|
Loading…
Reference in New Issue
Block a user