Merge branch 'feature' into 6000-cable-trace-svg

This commit is contained in:
jeremystretch 2021-07-16 16:46:32 -04:00
commit 145be09cfd
51 changed files with 468 additions and 324 deletions

View File

@ -27,7 +27,7 @@ For JavaScript, every `.ts` file in `netbox/project-static/src` is:
2. Minified
3. Combined into a single output file at `netbox/project-static/dist/netbox.js` (this includes any dependant libraries imported in a file)
Likewise, with Sass, each `*.scss` file is:
Likewise, with Sass, every `.scss` file in `netbox/project-static/styles` is:
1. Transpiled from Sass to CSS
2. Minified

View File

@ -27,11 +27,11 @@ if (args.includes('--no-cache')) {
// Style (SCSS) bundle jobs. Generally, everything should be bundled into netbox.css from main.scss
// unless there is a specific reason to do otherwise.
const styles = [
['_external.scss', 'netbox-external.css'],
['_light.scss', 'netbox-light.css'],
['_dark.scss', 'netbox-dark.css'],
['_elevations.scss', 'rack_elevation.css'],
['_cable_trace.scss', 'cable_trace.css'],
['styles/_external.scss', 'netbox-external.css'],
['styles/_light.scss', 'netbox-light.css'],
['styles/_dark.scss', 'netbox-dark.css'],
['styles/_elevations.scss', 'rack_elevation.css'],
['styles/_cable_trace.scss', 'cable_trace.css'],
];
// Script (JavaScript) bundle jobs. Generally, everything should be bundled into netbox.js from

View File

@ -1 +1 @@
{"version":3,"sources":["_cable_trace.scss"],"names":[],"mappings":"AAAA,EACI,sBAAA,CACA,eAEJ,KACI,kBAAA,CACA,yBAEJ,UACE,gBAKA,SACE,YAAA,CACA,cAAA,CACA,eACA,sBACE,aAKJ,oBACE,kBAEF,SACE,iBAEF,sBACE,cAAA,CACA,iBAEF,oBACE,aAAA,CACA","file":"cable_trace.css","sourceRoot":"..","sourcesContent":["* {\n font-family: sans-serif;\n font-size: 14px;\n}\ntext {\n text-anchor: middle;\n dominant-baseline: middle;\n}\ntext.bold {\n font-weight: bold;\n}\n\nsvg {\n /* Boxes */\n rect {\n fill: #e0e0e0;\n stroke: #606060;\n stroke-width: 1;\n .termination {\n fill: #f0f0f0;\n }\n }\n\n /* Connectors */\n .connector text {\n text-anchor: start;\n }\n line {\n stroke-width: 5px;\n }\n line.cable-shadow {\n stroke: #303030;\n stroke-width: 7px;\n }\n line.attachment {\n stroke: #c0c0c0;\n stroke-dasharray: 5px,5px;\n }\n}\n"]}
{"version":3,"sources":["_cable_trace.scss"],"names":[],"mappings":"AAAA,EACI,sBAAA,CACA,eAEJ,KACI,kBAAA,CACA,yBAEJ,UACE,gBAKA,SACE,YAAA,CACA,cAAA,CACA,eACA,sBACE,aAKJ,oBACE,kBAEF,SACE,iBAEF,sBACE,cAAA,CACA,iBAEF,oBACE,aAAA,CACA","file":"cable_trace.css","sourceRoot":"../styles","sourcesContent":["* {\n font-family: sans-serif;\n font-size: 14px;\n}\ntext {\n text-anchor: middle;\n dominant-baseline: middle;\n}\ntext.bold {\n font-weight: bold;\n}\n\nsvg {\n /* Boxes */\n rect {\n fill: #e0e0e0;\n stroke: #606060;\n stroke-width: 1;\n .termination {\n fill: #f0f0f0;\n }\n }\n\n /* Connectors */\n .connector text {\n text-anchor: start;\n }\n line {\n stroke-width: 5px;\n }\n line.cable-shadow {\n stroke: #303030;\n stroke-width: 7px;\n }\n line.attachment {\n stroke: #c0c0c0;\n stroke-dasharray: 5px,5px;\n }\n}\n"]}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

View File

@ -117,13 +117,41 @@ function initTabs() {
}
}
/**
* When accordion buttons are clicked, add a class to the parent accordion item. This is used
* for the side navigation to apply a box-shadow when the section is open.
*/
function initSidebarAccordions(): void {
const items = document.querySelectorAll<HTMLDivElement>('.sidebar .accordion-item');
function handleToggle(thisItem: HTMLDivElement) {
for (const item of items) {
if (item !== thisItem) {
// Remove the is-open class from all other accordion items, so that if one is clicked while
// another is open, the shadow is removed.
item.classList.remove('is-open');
} else {
item.classList.toggle('is-open');
}
}
}
for (const item of items) {
for (const button of item.querySelectorAll<HTMLButtonElement>('.accordion-button')) {
button.addEventListener('click', () => {
handleToggle(item);
});
}
}
}
/**
* Enable any defined Bootstrap Tooltips.
*
* @see https://getbootstrap.com/docs/5.0/components/tooltips
*/
export function initBootstrap(): void {
for (const func of [initTooltips, initModals, initMasonry, initTabs]) {
for (const func of [initTooltips, initModals, initMasonry, initTabs, initSidebarAccordions]) {
func();
}
}

View File

@ -0,0 +1,15 @@
import { isTruthy, getElements } from './util';
/**
* Allow any element to be made "clickable" with the use of the `data-href` attribute.
*/
export function initLinks() {
for (const link of getElements('*[data-href]')) {
const href = link.getAttribute('data-href');
if (isTruthy(href)) {
link.addEventListener('click', () => {
window.location.assign(href);
});
}
}
}

View File

@ -11,6 +11,7 @@ import { initTableConfig } from './tableConfig';
import { initInterfaceTable } from './tables';
import { initSideNav } from './sidenav';
import { initRackElevation } from './racks';
import { initLinks } from './links';
function init() {
for (const init of [
@ -27,6 +28,7 @@ function init() {
initInterfaceTable,
initSideNav,
initRackElevation,
initLinks,
]) {
init();
}

View File

@ -98,7 +98,11 @@
margin-bottom: $spacer;
}
// Use proper contrasting color for badge & progress-bar foreground color.
*[data-href] {
cursor: pointer;
}
// Use proper contrasting color foreground color for special components.
@each $color, $value in $theme-colors {
.badge,
.toast,
@ -107,6 +111,16 @@
color: color-contrast($value);
}
}
// Use proper foreground color in the alert body. Note: this is applied to a, p, & small because
// we *don't* want to override the h1-h6 colors for alerts, since those are set to a color
// similar to the alert color.
.alert.alert-#{$color} {
a,
p,
small {
color: color-contrast($value);
}
}
}
// Ensure progress bars (utilization graph) in tables aren't too narrow to display the percentage.
@ -114,6 +128,62 @@ table td > .progress {
min-width: 6rem;
}
.card > .table.table-flush {
margin-bottom: 0;
overflow: hidden;
border-bottom-right-radius: $card-border-radius;
border-bottom-left-radius: $card-border-radius;
thead th[scope='col'] {
background-color: $table-flush-header-bg;
vertical-align: middle;
text-transform: uppercase;
padding-top: map.get($spacers, 3);
padding-bottom: map.get($spacers, 3);
border-bottom-color: $card-border-color;
border-top: 1px solid $card-border-color;
}
th,
td {
border-left: 0;
border-right: 0;
padding-left: map.get($spacers, 4) !important;
padding-right: map.get($spacers, 4) !important;
}
tr[class] {
border-color: $card-border-color !important;
&:last-of-type {
border-bottom-color: transparent !important;
border-bottom-right-radius: $card-border-radius;
border-bottom-left-radius: $card-border-radius;
}
}
}
// Primarily used for the new release notification, but could be used for other alerts as needed.
// Wrap any alerts in .header-alert-container to ensure the layout is consistent.
.header-alert-container {
// Center-align the alert(s).
display: flex;
justify-content: center;
align-items: center;
// Apply the same spacing that's applied to the #content div's first child (.px-3).
padding: 0 $spacer;
// By default, alerts inside .header-alert-container should take up the full width.
.alert {
width: 100%;
// Adjust the max-width for larger screens so there's not a big ugly blue blob taking up the
// entire screen.
@include media-breakpoint-up(md) {
max-width: 75%;
}
@include media-breakpoint-up(lg) {
max-width: 50%;
}
}
}
span.profile-button .dropdown-menu {
transition: opacity 0.2s ease-in-out;
display: block !important;
@ -441,6 +511,12 @@ div.content-container {
div.accordion-item {
border: unset;
padding: 0 $spacer / 2;
// When an sidenav section is open, apply a shadow to provide a visual border.
&.is-open {
box-shadow: inset 0px -25px 20px -25px rgba($black, 0.25);
}
& > a.accordion-button {
&:not(.collapsed) {
@ -483,13 +559,13 @@ div.content-container {
}
}
div.position-sticky {
height: calc(100vh - 8rem);
height: calc(100vh - #{$sidebar-bottom-height});
}
div.sidebar-bottom {
padding-left: 0.5rem;
padding-right: 0.5rem;
position: sticky;
height: 8rem;
height: $sidebar-bottom-height;
background-color: var(--nbx-sidebar-bg);
@include media-breakpoint-down(md) {
@ -699,10 +775,38 @@ label.required {
}
}
// Applied to containing element around table bulk-action buttons (bulk-edit, bulk-disconnect
// bulk-delete, etc). Each usage of .bulk-buttons needs to have groups of buttons wrapped with
// .bulk-button-group so that proper spacing is applied (even if there is only one group).
div.bulk-buttons {
display: flex;
& > * {
margin: $spacer / 4;
justify-content: space-between;
margin: $spacer / 2 0;
// Each group of buttons needs to be contained separately for alignment purposes. This way, you
// can put some buttons in a group that aligns left, and other buttons in a group that aligns
// right.
& > div.bulk-button-group {
display: flex;
&:first-of-type:not(:last-of-type) {
// If there are multiple bulk button groups and this is the first, the first button in the
// group should *not* have left spacing applied, so the button group aligns with the rest
// of the page elements.
& > *:first-child {
margin-left: 0;
}
}
&:last-of-type:not(:first-of-type) {
// If there are multiple bulk button groups and this is the last, the last button in the
// group should *not* have right spacing applied, so the button group aligns with the rest
// of the page elements.
& > *:last-child {
margin-right: 0;
}
}
// However, the rest of the buttons should have spacing applied in all directions.
& > * {
margin: $spacer / 4;
}
}
}

View File

@ -245,3 +245,4 @@ $accordion-padding-y: 0.8125rem;
$accordion-padding-x: 0.8125rem;
$sidebar-width: 280px;
$sidebar-bottom-height: 4rem;

View File

@ -63,6 +63,7 @@ $table-active-color: $table-color;
$table-active-bg: rgba($white, $table-active-bg-factor);
$table-hover-color: $table-color;
$table-hover-bg: rgba($white, $table-hover-bg-factor);
$table-flush-header-bg: $gray-700;
// Buttons
$btn-box-shadow: inset 0 1px 0 rgba($black, 0.15), 0 1px 1px rgba($white, 0.075);

View File

@ -28,3 +28,5 @@ $code-color: $gray-900;
$list-group-color: $gray-700;
$list-group-disabled-color: $gray-500;
$table-flush-header-bg: $gray-100;

View File

@ -21,7 +21,7 @@
</a>
</div>
<ul class="nav flex-column px-1">
<ul class="nav flex-column">
{# Search bar for collapsed menu #}
<div class="d-block d-md-none mx-1 my-3 search-container">
@ -120,7 +120,6 @@
{# 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">{% annotated_now %} {% now 'T' %}</span>
<span class="ms-md-3 d-block d-md-inline">{{ settings.HOSTNAME }} (v{{ settings.VERSION }})</span>

View File

@ -6,37 +6,34 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DeviceConsolePortTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DeviceConsolePortTable_config" %}
{% render_table consoleport_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_consoleport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleport_bulk_rename' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_consoleport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:consoleport_bulk_delete' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_consoleport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleport_bulk_rename' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_consoleport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:consoleport_bulk_delete' %}?return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_consoleport %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:consoleport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleports' pk=object.pk %}" class="btn btn-sm btn-primary">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Console Port
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=consoleport_table.paginator page=consoleport_table.page %}

View File

@ -6,37 +6,34 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DeviceConsoleServerPortTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DeviceConsoleServerPortTable_config" %}
{% render_table consoleserverport_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_consoleserverport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleserverport_bulk_rename' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleserverport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_consoleserverport %}
<button type="submit" formaction="{% url 'dcim:consoleserverport_bulk_delete' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_consoleserverport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:consoleserverport_bulk_rename' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:consoleserverport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:consoleserverport_bulk_disconnect' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_consoleserverport %}
<button type="submit" formaction="{% url 'dcim:consoleserverport_bulk_delete' %}?return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_consoleserverport %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:consoleserverport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_consoleserverports' pk=object.pk %}" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Console Server Ports
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=consoleserverport_table.paginator page=consoleserverport_table.page %}

View File

@ -6,34 +6,31 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DeviceDeviceBayTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DeviceDeviceBayTable_config" %}
{% render_table devicebay_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_devicebay %}
<button type="submit" name="_rename" formaction="{% url 'dcim:devicebay_bulk_rename' %}?return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:devicebay_bulk_edit' %}?device={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
{% endif %}
{% if perms.dcim.delete_devicebay %}
<button type="submit" formaction="{% url 'dcim:devicebay_bulk_delete' %}?return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-outline-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete selected
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_devicebay %}
<button type="submit" name="_rename" formaction="{% url 'dcim:devicebay_bulk_rename' %}?return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:devicebay_bulk_edit' %}?device={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
{% endif %}
{% if perms.dcim.delete_devicebay %}
<button type="submit" formaction="{% url 'dcim:devicebay_bulk_delete' %}?return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-outline-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete selected
</button>
{% endif %}
</div>
{% if perms.dcim.add_devicebay %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:devicebay_add' %}?device={{ object.pk }}&return_url={{ object.get_absolute_url }}%23tab_devicebays" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Device Bays
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=devicebay_table.paginator page=devicebay_table.page %}

View File

@ -6,37 +6,34 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DeviceFrontPortTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DeviceFrontPortTable_config" %}
{% render_table frontport_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_frontport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:frontport_bulk_rename' %}?return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:frontport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:frontport_bulk_disconnect' %}?return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_frontport %}
<button type="submit" formaction="{% url 'dcim:frontport_bulk_delete' %}?return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_frontport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:frontport_bulk_rename' %}?return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:frontport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:frontport_bulk_disconnect' %}?return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_frontport %}
<button type="submit" formaction="{% url 'dcim:frontport_bulk_delete' %}?return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_frontport %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:frontport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_frontports' pk=object.pk %}" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add front ports
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=frontport_table.paginator page=frontport_table.page %}

View File

@ -6,30 +6,37 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end col-md-4 noprint table-controls mw-33">
<div class="input-group input-group-sm">
<input type="text" class="form-control interface-filter" placeholder="Filter" title="Filter text (regular expressions supported)" />
<button class="btn btn-sm btn-outline-dark dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="mdi mdi-table-cog"></i>
</button>
<ul class="dropdown-menu">
<div class="row mb-3 justify-content-between">
<div class="col col-md-2 float-end noprint table-controls mb-0 mw-33">
<div class="input-group input-group-sm">
{% if request.user.is_authenticated %}
<button
type="button"
class="dropdown-item"
class="btn btn-sm btn-outline-dark"
data-bs-toggle="modal"
data-bs-target="#DeviceInterfaceTable_config"
title="Configure Table">
Configure Table
<i class="mdi mdi-cog"></i> Configure Table
</button>
{% endif %}
<button type="button" class="dropdown-item toggle-enabled" data-state="show">Hide Enabled</button>
<button type="button" class="dropdown-item toggle-disabled" data-state="show">Hide Disabled</button>
</ul>
{% endif %}
<button class="btn btn-sm btn-outline-dark dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
<i class="mdi mdi-eye"></i>
</button>
<ul class="dropdown-menu">
<button type="button" class="dropdown-item toggle-enabled" data-state="show">Hide Enabled</button>
<button type="button" class="dropdown-item toggle-disabled" data-state="show">Hide Disabled</button>
</ul>
</div>
</div>
<div class="col col-md-4 float-end noprint table-controls mw-33">
<div class="input-group input-group-sm">
<input type="text" class="form-control interface-filter" placeholder="Filter" title="Filter text (regular expressions supported)" />
</div>
</div>
</div>
{% render_table interface_table 'inc/table.html' %}
<div class="noprint">
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_interface %}
<button type="submit" name="_rename" formaction="{% url 'dcim:interface_bulk_rename' %}?return_url={% url 'dcim:device_interfaces' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
@ -46,14 +53,14 @@
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_interface %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:interface_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_interfaces' pk=object.pk %}" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Interfaces
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=interface_table.paginator page=interface_table.page %}

View File

@ -6,28 +6,26 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DeviceInventoryItemTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DeviceInventoryItemTable_config" %}
{% render_table inventoryitem_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_inventoryitem %}
<button type="submit" name="_rename" formaction="{% url 'dcim:inventoryitem_bulk_rename' %}?return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:inventoryitem_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
{% endif %}
{% if perms.dcim.delete_inventoryitem %}
<button type="submit" name="_delete" formaction="{% url 'dcim:inventoryitem_bulk_delete' %}?return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_inventoryitem %}
<button type="submit" name="_rename" formaction="{% url 'dcim:inventoryitem_bulk_rename' %}?return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:inventoryitem_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
{% endif %}
{% if perms.dcim.delete_inventoryitem %}
<button type="submit" name="_delete" formaction="{% url 'dcim:inventoryitem_bulk_delete' %}?return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_inventoryitem %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:inventoryitem_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_inventory' pk=object.pk %}" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Inventory Item
</a>

View File

@ -6,37 +6,34 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DevicePowerOutletTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DevicePowerOutletTable_config" %}
{% render_table poweroutlet_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_powerport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:poweroutlet_bulk_rename' %}?return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:poweroutlet_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:poweroutlet_bulk_disconnect' %}?return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_poweroutlet %}
<button type="submit" formaction="{% url 'dcim:poweroutlet_bulk_delete' %}?return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_powerport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:poweroutlet_bulk_rename' %}?return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:poweroutlet_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:poweroutlet_bulk_disconnect' %}?return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_poweroutlet %}
<button type="submit" formaction="{% url 'dcim:poweroutlet_bulk_delete' %}?return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_poweroutlet %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:poweroutlet_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_poweroutlets' pk=object.pk %}" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Power Outlets
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=poweroutlet_table.paginator page=poweroutlet_table.page %}

View File

@ -6,37 +6,34 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DevicePowerPortTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DevicePowerPortTable_config" %}
{% render_table powerport_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_powerport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:powerport_bulk_rename' %}?return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:powerport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:powerport_bulk_disconnect' %}?return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_powerport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:powerport_bulk_delete' %}?return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_powerport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:powerport_bulk_rename' %}?return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:powerport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:powerport_bulk_disconnect' %}?return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_powerport %}
<button type="submit" name="_delete" formaction="{% url 'dcim:powerport_bulk_delete' %}?return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_powerport %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:powerport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_powerports' pk=object.pk %}" class="btn btn-sm btn-primary">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add power port
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add Power Port
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=powerport_table.paginator page=powerport_table.page %}

View File

@ -6,37 +6,34 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end noprint">
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#DeviceRearPortTable_config" title="Configure table"><i class="mdi mdi-cog"></i> Configure</button>
{% endif %}
</div>
{% include 'inc/table_controls.html' with table_modal="DeviceRearPortTable_config" %}
{% render_table rearport_table 'inc/table.html' %}
<div class="noprint">
{% if perms.dcim.change_rearport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:rearport_bulk_rename' %}?return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:rearport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:rearport_bulk_disconnect' %}?return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_rearport %}
<button type="submit" formaction="{% url 'dcim:rearport_bulk_delete' %}?return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% if perms.dcim.change_rearport %}
<button type="submit" name="_rename" formaction="{% url 'dcim:rearport_bulk_rename' %}?return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-outline-warning btn-sm">
<i class="mdi mdi-pencil-outline" aria-hidden="true"></i> Rename
</button>
<button type="submit" name="_edit" formaction="{% url 'dcim:rearport_bulk_edit' %}?device={{ object.pk }}&return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit
</button>
<button type="submit" name="_disconnect" formaction="{% url 'dcim:rearport_bulk_disconnect' %}?return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-outline-danger btn-sm">
<span class="mdi mdi-ethernet-cable-off" aria-hidden="true"></span> Disconnect
</button>
{% endif %}
{% if perms.dcim.delete_rearport %}
<button type="submit" formaction="{% url 'dcim:rearport_bulk_delete' %}?return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete
</button>
{% endif %}
</div>
{% if perms.dcim.add_rearport %}
<div class="float-end">
<div class="bulk-button-group">
<a href="{% url 'dcim:rearport_add' %}?device={{ object.pk }}&return_url={% url 'dcim:device_rearports' pk=object.pk %}" class="btn btn-primary btn-sm">
<i class="mdi mdi-plus-thick" aria-hidden="true"></i> Add rear ports
</a>
</div>
{% endif %}
<div class="clearfix"></div>
</div>
</form>
{% include 'inc/paginator.html' with paginator=rearport_table.paginator page=rearport_table.page %}

View File

@ -23,17 +23,17 @@
<i class="mdi mdi-file-image-outline"></i>
Hide Images
</button>
<a {% if prev_rack %}href="{% url 'dcim:rack' pk=prev_rack.pk %}"{% else %}disabled="disabled"{% endif %} class="btn btn-sm btn-primary m-1">
<a {% if prev_rack %}href="{% url 'dcim:rack' pk=prev_rack.pk %}{% endif %}" class="btn btn-sm btn-primary m-1{% if not prev_rack %} disabled{% endif %}">
<i class="mdi mdi-chevron-left" aria-hidden="true"></i> Previous Rack
</a>
<a {% if next_rack %}href="{% url 'dcim:rack' pk=next_rack.pk %}"{% else %}disabled="disabled"{% endif %} class="btn btn-sm btn-primary m-1">
<a {% if next_rack %}href="{% url 'dcim:rack' pk=next_rack.pk %}{% endif %}" class="btn btn-sm btn-primary m-1{% if not next_rack %} disabled{% endif %}">
<i class="mdi mdi-chevron-right" aria-hidden="true"></i> Next Rack
</a>
{% endblock %}
{% block content %}
<div class="row">
<div class="col col-md-6">
<div class="col col-12 col-xl-6">
<div class="card">
<h5 class="card-header">
Rack
@ -310,7 +310,7 @@
</div>
{% plugin_left_page object %}
</div>
<div class="col col-md-6">
<div class="col col-12 col-xl-6">
<div class="row" style="margin-bottom: 20px">
<div class="col col-md-6 col-sm-6 col-xs-12 text-center">
<div style="margin-left: 30px">

View File

@ -15,23 +15,6 @@
<li class="breadcrumb-item">{{ object }}</li>
{% endblock %}
{% block header %}
<div class="row noprint">
<div class="col col-sm-4 col-md-3">
<form action="{% url 'extras:objectchange_list' %}" method="get">
<div class="input-group">
<input type="text" name="q" class="form-control" />
<span class="input-group-btn">
<button type="submit" class="btn btn-primary">
<span class="mdi mdi-magnify" aria-hidden="true"></span>
</button>
</span>
</div>
</form>
</div>
</div>
{% endblock %}
{% block content %}
<div class="row mb-3">
<div class="col col-md-5">

View File

@ -58,27 +58,7 @@
{% endif %}
{# Object list filter, table config #}
<div class="row mb-3">
<div class="col col-md-4 offset-md-8 d-flex noprint table-controls">
<div class="input-group input-group-sm">
<input type="text" class="form-control object-filter" placeholder="Filter" title="Filter text (regular expressions supported)" />
{% if request.user.is_authenticated and table_config_form %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#ObjectTable_config" title="Configure Table">
<i class="mdi mdi-table-eye"></i>
</button>
{% endif %}
{% if filter_form %}
<button
type="button"
class="btn btn-sm btn-outline-dark"
data-bs-toggle="collapse"
data-bs-target="#advanced-search-content">
Advanced Search
</button>
{% endif %}
</div>
</div>
</div>
{% include 'inc/table_controls.html' with table_modal="ObjectTable_config" %}
{# Object table #}
<div class="row">
@ -91,18 +71,20 @@
<div class="table-responsive">
{% render_table table 'inc/table.html' %}
</div>
<div class="float-start noprint bulk-buttons">
{% block bulk_buttons %}{% endblock %}
{% if bulk_edit_url and permissions.change %}
<button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
</button>
{% endif %}
{% if bulk_delete_url and permissions.delete %}
<button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
</button>
{% endif %}
<div class="noprint bulk-buttons">
<div class="bulk-button-group">
{% block bulk_buttons %}{% endblock %}
{% if bulk_edit_url and permissions.change %}
<button type="submit" name="_edit" formaction="{% url bulk_edit_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-warning btn-sm">
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit Selected
</button>
{% endif %}
{% if bulk_delete_url and permissions.delete %}
<button type="submit" name="_delete" formaction="{% url bulk_delete_url %}{% if request.GET %}?{{ request.GET.urlencode }}{% endif %}" class="btn btn-danger btn-sm">
<i class="mdi mdi-trash-can-outline" aria-hidden="true"></i> Delete Selected
</button>
{% endif %}
</div>
</div>
</form>
{% else %}

View File

@ -2,7 +2,25 @@
{% load get_status %}
{% load helpers %}
{% block header %}{% endblock %}
{% block header %}
{{ block.super }}
{% if new_release %}
{# new_release is set only if the current user is a superuser or staff member #}
<div class="header-alert-container">
<div class="alert alert-info text-center mw-md-50" role="alert">
<h6 class="alert-heading">
<i class="mdi mdi-information-outline"></i><br/>New Release Available
</h6>
<small><a href="{{ new_release.url }}">NetBox v{{ new_release.version }}</a> is available.</small>
<hr class="my-2" />
<small class="mb-0">
<a href="https://netbox.readthedocs.io/en/stable/installation/upgrading/">Upgrade Instructions</a>
</small>
</div>
</div>
{% endif %}
{% endblock %}
{% block title %}Home{% endblock %}
{% block content %}
@ -35,47 +53,42 @@
{# Changelog #}
<div class="row my-4 flex-grow-1 changelog-container">
<div class="col">
<h5 class="text-center">Changelog</h5>
{% if changelog and perms.extras.view_objectchange %}
{# TODO: Replace this with a django-tables2 Table #}
<table class="table align-middle table-hover">
<thead>
<tr>
<th scope="col">User</th>
<th scope="col">Action</th>
<th scope="col">Type</th>
<th scope="col">Object</th>
<th scope="col">Time</th>
<th scope="col" align="right"></th>
</tr>
</thead>
<tbody>
{% for change in changelog %}
<tr class="{% get_status change.get_action_display %}">
<th scope="row">{{ change.user|default:change.user_name }}</th>
<td>{{ change.get_action_display|bettertitle }}</td>
<td>{{ change.changed_object_type.name|bettertitle }}</td>
<td>
{% if change.changed_object.get_absolute_url %}
<a class="text-body" href="{{ change.changed_object.get_absolute_url }}">{{ change.changed_object }}</a>
{% else %} {{ change.changed_object|default:change.object_repr }} {% endif %}
</td>
<td>{{ change.time|date:'SHORT_DATETIME_FORMAT' }}</td>
<td>
<a role="button" class="text-body" href="{{ change.get_absolute_url }}">
<i class="mdi mdi-dots-horizontal" data-bs-toggle="tooltip" data-bs-placement="left" title="View Change Details"></i>
</a>
</td>
</tr>
{% endfor %}
</tbody>
</table>
{% elif perms.extras.view_objectchange %}
<div class="alert alert-secondary mt-4" role="alert">
No change history found.
<div class="card">
<h6 class="card-header text-primary text-center">Changelog</h6>
{% if changelog and perms.extras.view_objectchange %}
{# TODO: Replace this with a django-tables2 Table #}
<table class="table table-flush align-middle table-hover">
<thead>
<tr>
<th scope="col">User</th>
<th scope="col">Action</th>
<th scope="col">Type</th>
<th scope="col">Object</th>
<th scope="col">Time</th>
</tr>
</thead>
<tbody>
{% for change in changelog %}
<tr class="{% get_status change.get_action_display %}" data-href="{{ change.get_absolute_url }}">
<th scope="row">{{ change.user|default:change.user_name }}</th>
<td>{{ change.get_action_display|bettertitle }}</td>
<td>{{ change.changed_object_type.name|bettertitle }}</td>
<td>
{% if change.changed_object.get_absolute_url %}
<a class="text-body" href="{{ change.changed_object.get_absolute_url }}">{{ change.changed_object }}</a>
{% else %} {{ change.changed_object|default:change.object_repr }} {% endif %}
</td>
<td>{{ change.time|date:'SHORT_DATETIME_FORMAT' }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% elif perms.extras.view_objectchange %}
<div class="alert alert-secondary mt-4" role="alert">
No change history found.
</div>
{% endif %}
</div>
{% endif %}
</div>
</div>
{% endblock content %}

View File

@ -0,0 +1,37 @@
<div class="row mb-3 justify-content-between">
<div class="col col-md-2 mb-0 d-flex noprint table-controls">
{% if request.user.is_authenticated %}
<div class="input-group input-group-sm">
<button
type="button"
data-bs-toggle="modal"
title="Configure Table"
data-bs-target="#{{ table_modal }}"
class="btn btn-sm btn-outline-dark"
>
<i class="mdi mdi-cog"></i> Configure Table
</button>
</div>
{% endif %}
</div>
<div class="col col-md-4 d-flex noprint table-controls">
<div class="input-group input-group-sm">
<input
type="text"
class="form-control object-filter"
placeholder="Filter"
title="Filter text (regular expressions supported)"
/>
{% if filter_form %}
<button
type="button"
class="btn btn-sm btn-outline-dark"
data-bs-toggle="collapse"
data-bs-target="#advanced-search-content"
>
Advanced Search
</button>
{% endif %}
</div>
</div>
</div>

View File

@ -6,14 +6,7 @@
{% block content %}
<form method="post">
{% csrf_token %}
<div class="float-end col-md-4 noprint table-controls mw-33">
<div class="input-group input-group-sm">
<input type="text" class="form-control interface-filter" placeholder="Filter" title="Filter text (regular expressions supported)" />
{% if request.user.is_authenticated %}
<button type="button" class="btn btn-outline-dark btn-sm" data-bs-toggle="modal" data-bs-target="#VirtualMachineVMInterfaceTable_config" title="Configure Table"><i class="mdi mdi-table-eye"></i></button>
{% endif %}
</div>
</div>
{% include 'inc/table_controls.html' with table_modal="VirtualMachineVMInterfaceTable_config" %}
{% render_table interface_table 'inc/table.html' %}
<div class="noprint">
{% if perms.virtualization.change_vminterface %}