mirror of
https://github.com/netbox-community/netbox.git
synced 2026-01-24 20:39:59 -06:00
#6372: Implement layout improvements
This commit is contained in:
@@ -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';
|
||||
|
||||
2
netbox/project-static/dist/netbox-dark.css
vendored
2
netbox/project-static/dist/netbox-dark.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
netbox/project-static/dist/netbox-light.css
vendored
2
netbox/project-static/dist/netbox-light.css
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
323
netbox/project-static/dist/netbox.js
vendored
323
netbox/project-static/dist/netbox.js
vendored
File diff suppressed because one or more lines are too long
2
netbox/project-static/dist/netbox.js.map
vendored
2
netbox/project-static/dist/netbox.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
|
||||
*{font-family: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-size:.875rem}rect{box-sizing:border-box}text{text-anchor:middle;dominant-baseline:middle}svg .rack{background-color:#f3f4f6;fill:none;stroke:#111827;stroke-width:2px}svg .slot{fill:#f3f4f6;stroke:#6b7280}svg .slot:hover{fill:#f9fafb}svg .slot+.add-device{fill:none}svg .slot .add-device:hover,svg .slot:hover+.add-device{fill:#3b82f6}svg .slot .add-device:hover+.slot{fill:#fff}svg .slot.reserved:hover[class],svg .slot.reserved[class]{fill:url(#reserved)}svg .slot.occupied:hover[class],svg .slot.occupied[class]{fill:url(#occupied)}svg .slot.blocked:hover[class],svg .slot.blocked[class]{fill:url(#blocked)}svg .slot.blocked:hover+.add-device{fill:none}svg .unit{margin:0;padding:5px 0;fill:#9ca3af;font-size:.875rem;font-family: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}svg .hidden{visibility:hidden}svg[data-netbox-color-mode=dark] .rack{background-color:#1f2937}svg[data-netbox-color-mode=dark] .slot{fill:#374151;stroke:#9ca3af}svg[data-netbox-color-mode=dark] .slot:hover{fill:#4b5563}svg[data-netbox-color-mode=dark] .slot+.add-device{fill:none}svg[data-netbox-color-mode=dark] .add-device:hover,svg[data-netbox-color-mode=dark] .slot:hover+.add-device{fill:#93c5fd}svg[data-netbox-color-mode=dark] .add-device:hover+.slot{fill:#000}
|
||||
*{font-family: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-size:.875rem}rect{box-sizing:border-box}text{text-anchor:middle;dominant-baseline:middle}svg .rack{background-color:#f3f4f6;fill:none;stroke:#111827;stroke-width:2px}svg .slot{fill:#f3f4f6;stroke:#6b7280}svg .slot:hover{fill:#f9fafb}svg .slot+.add-device{fill:none}svg .slot .add-device:hover,svg .slot:hover+.add-device{fill:#3b82f6}svg .slot .add-device:hover+.slot{fill:#fff}svg .slot.reserved:hover[class],svg .slot.reserved[class]{fill:url(#reserved)}svg .slot.occupied:hover[class],svg .slot.occupied[class]{fill:url(#occupied)}svg .slot.blocked:hover[class],svg .slot.blocked[class]{fill:url(#blocked)}svg .slot.blocked:hover+.add-device{fill:none}svg .unit{margin:0;padding:5px 0;fill:#9ca3af;font-size:.875rem;font-family: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}svg .hidden{visibility:hidden}svg[data-netbox-color-mode=dark] .rack{background-color:#1f2937}svg[data-netbox-color-mode=dark] .slot{fill:#374151;stroke:#9ca3af}svg[data-netbox-color-mode=dark] .slot:hover{fill:#4b5563}svg[data-netbox-color-mode=dark] .slot+.add-device{fill:none}svg[data-netbox-color-mode=dark] .add-device:hover,svg[data-netbox-color-mode=dark] .slot:hover+.add-device{fill:#93c5fd}svg[data-netbox-color-mode=dark] .add-device:hover+.slot{fill:#000}
|
||||
/*# sourceMappingURL=/static/rack_elevation.css.map */
|
||||
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",
|
||||
|
||||
Reference in New Issue
Block a user