mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
bootstrap 5 class updates
This commit is contained in:
@ -33,7 +33,7 @@ IPADDRESS_LINK = """
|
||||
{% if record.pk %}
|
||||
<a href="{{ record.get_absolute_url }}">{{ record.address }}</a>
|
||||
{% elif perms.ipam.add_ipaddress %}
|
||||
<a href="{% url 'ipam:ipaddress_add' %}?address={{ record.1 }}{% if object.vrf %}&vrf={{ object.vrf.pk }}{% endif %}{% if object.tenant %}&tenant={{ object.tenant.pk }}{% endif %}" class="btn btn-xs btn-success">{% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available</a>
|
||||
<a href="{% url 'ipam:ipaddress_add' %}?address={{ record.1 }}{% if object.vrf %}&vrf={{ object.vrf.pk }}{% endif %}{% if object.tenant %}&tenant={{ object.tenant.pk }}{% endif %}" class="btn btn-sm btn-success">{% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available</a>
|
||||
{% else %}
|
||||
{% if record.0 <= 65536 %}{{ record.0 }}{% else %}Many{% endif %} IP{{ record.0|pluralize }} available
|
||||
{% endif %}
|
||||
@ -65,7 +65,7 @@ VLAN_LINK = """
|
||||
{% if record.pk %}
|
||||
<a href="{{ record.get_absolute_url }}">{{ record.vid }}</a>
|
||||
{% elif perms.ipam.add_vlan %}
|
||||
<a href="{% url 'ipam:vlan_add' %}?vid={{ record.vid }}&group={{ vlan_group.pk }}{% if vlan_group.site %}&site={{ vlan_group.site.pk }}{% endif %}" class="btn btn-xs btn-success">{{ record.available }} VLAN{{ record.available|pluralize }} available</a>
|
||||
<a href="{% url 'ipam:vlan_add' %}?vid={{ record.vid }}&group={{ vlan_group.pk }}{% if vlan_group.site %}&site={{ vlan_group.site.pk }}{% endif %}" class="btn btn-sm btn-success">{{ record.available }} VLAN{{ record.available|pluralize }} available</a>
|
||||
{% else %}
|
||||
{{ record.available }} VLAN{{ record.available|pluralize }} available
|
||||
{% endif %}
|
||||
@ -90,7 +90,7 @@ VLAN_ROLE_LINK = """
|
||||
VLANGROUP_ADD_VLAN = """
|
||||
{% with next_vid=record.get_next_available_vid %}
|
||||
{% if next_vid and perms.ipam.add_vlan %}
|
||||
<a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-xs btn-success">
|
||||
<a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-sm btn-success">
|
||||
<i class="mdi mdi-plus-thick" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
@ -245,7 +245,8 @@ span.color-label {
|
||||
}
|
||||
|
||||
textarea#id_local_context_data,
|
||||
textarea.markdown {
|
||||
textarea.markdown,
|
||||
textarea#id_public_key {
|
||||
font-family: $font-family-monospace;
|
||||
}
|
||||
|
||||
@ -355,3 +356,7 @@ span.bi-plus:before {
|
||||
table tbody tr.success {
|
||||
background-color: rgba($success, 0.15);
|
||||
}
|
||||
table td,
|
||||
table th {
|
||||
font-size: $font-size-sm;
|
||||
}
|
||||
|
8
netbox/project-static/src/clipboard.ts
Normal file
8
netbox/project-static/src/clipboard.ts
Normal file
@ -0,0 +1,8 @@
|
||||
import Clipboard from 'clipboard';
|
||||
import { getElements } from './util';
|
||||
|
||||
export function initClipboard() {
|
||||
for (const element of getElements('a.copy-token', 'button.copy-secret')) {
|
||||
new Clipboard(element);
|
||||
}
|
||||
}
|
5
netbox/project-static/src/global.d.ts
vendored
5
netbox/project-static/src/global.d.ts
vendored
@ -26,6 +26,11 @@ type APIObjectBase = {
|
||||
[k: string]: JSONAble;
|
||||
};
|
||||
|
||||
type APIKeyPair = {
|
||||
public_key: string;
|
||||
private_key: string;
|
||||
};
|
||||
|
||||
type APIReference = {
|
||||
id: number;
|
||||
name: string;
|
||||
|
@ -1,5 +1,4 @@
|
||||
import 'babel-polyfill';
|
||||
import '@popperjs/core';
|
||||
import 'bootstrap';
|
||||
import 'clipboard';
|
||||
import './netbox';
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { Tooltip } from 'bootstrap';
|
||||
import { Modal, Tooltip } from 'bootstrap';
|
||||
import Masonry from 'masonry-layout';
|
||||
import { initApiSelect, initStaticSelect, initColorSelect } from './select';
|
||||
import { initDateSelector } from './dateSelector';
|
||||
import { initMessageToasts } from './toast';
|
||||
import { initSpeedSelector, initForms } from './forms';
|
||||
import { initRackElevation } from './buttons';
|
||||
import { initClipboard } from './clipboard';
|
||||
import { initSearchBar } from './search';
|
||||
// import { initGenerateKeyPair } from './secrets';
|
||||
import { getElements } from './util';
|
||||
|
||||
const INITIALIZERS = [
|
||||
@ -18,6 +20,8 @@ const INITIALIZERS = [
|
||||
initSpeedSelector,
|
||||
initColorSelect,
|
||||
initRackElevation,
|
||||
initClipboard,
|
||||
// initGenerateKeyPair,
|
||||
] as (() => void)[];
|
||||
|
||||
/**
|
||||
@ -30,6 +34,10 @@ function initBootstrap(): void {
|
||||
for (const tooltip of getElements('[data-bs-toggle="tooltip"]')) {
|
||||
new Tooltip(tooltip, { container: 'body', boundary: 'window' });
|
||||
}
|
||||
for (const modal of getElements('[data-bs-toggle="modal"]')) {
|
||||
// for (const modal of getElements('div.modal')) {
|
||||
new Modal(modal);
|
||||
}
|
||||
initMessageToasts();
|
||||
initForms();
|
||||
}
|
||||
|
62
netbox/project-static/src/secrets.ts
Normal file
62
netbox/project-static/src/secrets.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { apiGetBase, getElements, isApiError } from './util';
|
||||
/**
|
||||
*
|
||||
* $('#generate_keypair').click(function() {
|
||||
$('#new_keypair_modal').modal('show');
|
||||
$.ajax({
|
||||
url: netbox_api_path + 'secrets/generate-rsa-key-pair/',
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
success: function (response, status) {
|
||||
var public_key = response.public_key;
|
||||
var private_key = response.private_key;
|
||||
$('#new_pubkey').val(public_key);
|
||||
$('#new_privkey').val(private_key);
|
||||
},
|
||||
error: function (xhr, ajaxOptions, thrownError) {
|
||||
alert("There was an error generating a new key pair.");
|
||||
}
|
||||
});
|
||||
});
|
||||
*/
|
||||
export function initGenerateKeyPair() {
|
||||
const element = document.getElementById('new_keypair_modal') as HTMLDivElement;
|
||||
const accept = document.getElementById('use_new_pubkey') as HTMLButtonElement;
|
||||
const publicElem = element.querySelector<HTMLTextAreaElement>('textarea#new_pubkey');
|
||||
const privateElem = element.querySelector<HTMLTextAreaElement>('textarea#new_privkey');
|
||||
|
||||
function handleOpen() {
|
||||
for (const elem of [publicElem, privateElem]) {
|
||||
if (elem !== null) {
|
||||
elem.setAttribute('readonly', '');
|
||||
}
|
||||
}
|
||||
|
||||
apiGetBase<APIKeyPair>('/api/secrets/generate-rsa-key-pair').then(data => {
|
||||
if (!isApiError(data)) {
|
||||
const { private_key: priv, public_key: pub } = data;
|
||||
if (publicElem !== null && privateElem !== null) {
|
||||
publicElem.value = pub;
|
||||
privateElem.value = priv;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function handleAccept() {
|
||||
const publicKeyField = document.getElementById('id_public_key') as HTMLTextAreaElement;
|
||||
if (publicElem !== null) {
|
||||
publicKeyField.value = publicElem.value;
|
||||
publicKeyField.innerText = publicElem.value;
|
||||
}
|
||||
}
|
||||
element.addEventListener('shown.bs.modal', handleOpen);
|
||||
accept.addEventListener('click', handleAccept);
|
||||
}
|
||||
|
||||
export function initLockUnlock() {
|
||||
for (const element of getElements<HTMLButtonElement>('button.unlock-secret')) {
|
||||
function handleClick() {
|
||||
const { secretId } = element.dataset;
|
||||
}
|
||||
}
|
||||
}
|
@ -32,6 +32,18 @@ export function getCsrfToken(): string {
|
||||
return csrfToken;
|
||||
}
|
||||
|
||||
export async function apiGetBase<T extends Record<string, unknown>>(
|
||||
url: string,
|
||||
): Promise<T | APIError> {
|
||||
const token = getCsrfToken();
|
||||
const res = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: { 'X-CSRFToken': token },
|
||||
});
|
||||
const json = (await res.json()) as T | APIError;
|
||||
return json;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch data from the NetBox API (authenticated).
|
||||
* @param url API endpoint
|
||||
@ -39,13 +51,7 @@ export function getCsrfToken(): string {
|
||||
export async function getApiData<T extends APIObjectBase>(
|
||||
url: string,
|
||||
): Promise<APIAnswer<T> | APIError> {
|
||||
const token = getCsrfToken();
|
||||
const res = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: { 'X-CSRFToken': token },
|
||||
});
|
||||
const json = (await res.json()) as APIAnswer<T> | APIError;
|
||||
return json;
|
||||
return await apiGetBase<APIAnswer<T>>(url);
|
||||
}
|
||||
|
||||
export function getElements<K extends keyof SVGElementTagNameMap>(
|
||||
|
@ -73,7 +73,7 @@ class SecretListView(generic.ObjectListView):
|
||||
filterset = filters.SecretFilterSet
|
||||
filterset_form = forms.SecretFilterForm
|
||||
table = tables.SecretTable
|
||||
action_buttons = ('import', 'export')
|
||||
action_buttons = ('add', 'import', 'export')
|
||||
|
||||
|
||||
class SecretView(generic.ObjectView):
|
||||
|
@ -215,16 +215,4 @@
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% if perms.extras.view_objectchange %}
|
||||
<li
|
||||
role="presentation"
|
||||
class="nav-item">
|
||||
<a
|
||||
href="{% url 'dcim:device_changelog' pk=object.pk %}"
|
||||
class="nav-link{% if active_tab == 'changelog' %} active{% endif %}"
|
||||
>
|
||||
Change Log
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -1,10 +1,10 @@
|
||||
{% if perms.dcim.change_cable %}
|
||||
{% if cable.status == 'connected' %}
|
||||
<a href="#" class="btn btn-warning btn-xs cable-toggle connected" title="Mark planned" data="{{ cable.pk }}">
|
||||
<a href="#" class="btn btn-warning btn-sm cable-toggle connected" title="Mark Planned" data="{{ cable.pk }}">
|
||||
<i class="mdi mdi-lan-disconnect" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="#" class="btn btn-success btn-xs cable-toggle" title="Mark installed" data="{{ cable.pk }}">
|
||||
<a href="#" class="btn btn-success btn-sm cable-toggle" title="Mark Installed" data="{{ cable.pk }}">
|
||||
<i class="mdi mdi-lan-connect" aria-hidden="true"></i>
|
||||
</a>
|
||||
{% endif %}
|
||||
|
@ -6,13 +6,13 @@
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{% url 'dcim:powerfeed_list' %}">Power Feeds</a></li>
|
||||
<li><a href="{{ object.power_panel.site.get_absolute_url }}">{{ object.power_panel.site }}</a></li>
|
||||
<li><a href="{{ object.power_panel.get_absolute_url }}">{{ object.power_panel }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'dcim:powerfeed_list' %}">Power Feeds</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.power_panel.site.get_absolute_url }}">{{ object.power_panel.site }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.power_panel.get_absolute_url }}">{{ object.power_panel }}</a></li>
|
||||
{% if object.rack %}
|
||||
<li><a href="{{ object.rack.get_absolute_url }}">{{ object.rack }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.rack.get_absolute_url }}">{{ object.rack }}</a></li>
|
||||
{% endif %}
|
||||
<li>{{ object }}</li>
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -25,13 +25,13 @@
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<td>Power Panel</td>
|
||||
<th scope="row">Power Panel</th>
|
||||
<td>
|
||||
<a href="{{ object.power_panel.get_absolute_url }}">{{ object.power_panel }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Rack</td>
|
||||
<th scope="row">Rack</th>
|
||||
<td>
|
||||
{% if object.rack %}
|
||||
<a href="{{ object.rack.get_absolute_url }}">{{ object.rack }}</a>
|
||||
@ -41,19 +41,19 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<th scope="row">Type</th>
|
||||
<td>
|
||||
<span class="badge bg-{{ object.get_type_class }}">{{ object.get_type_display }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<th scope="row">Status</th>
|
||||
<td>
|
||||
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Connected Device</td>
|
||||
<th scope="row">Connected Device</th>
|
||||
<td>
|
||||
{% if object.connected_endpoint %}
|
||||
<a href="{{ object.connected_endpoint.device.get_absolute_url }}">{{ object.connected_endpoint.device }}</a> ({{ object.connected_endpoint }})
|
||||
@ -63,7 +63,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Utilization (Allocated)</td>
|
||||
<th scope="row">Utilization (Allocated)</th>
|
||||
{% with utilization=object.connected_endpoint.get_power_draw %}
|
||||
{% if utilization %}
|
||||
<td>
|
||||
@ -87,23 +87,23 @@
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<td>Supply</td>
|
||||
<th scope="row">Supply</th>
|
||||
<td>{{ object.get_supply_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Voltage</td>
|
||||
<th scope="row">Voltage</th>
|
||||
<td>{{ object.voltage }}V</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Amperage</td>
|
||||
<th scope="row">Amperage</th>
|
||||
<td>{{ object.amperage }}A</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Phase</td>
|
||||
<th scope="row">Phase</th>
|
||||
<td>{{ object.get_phase_display }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Max Utilization</td>
|
||||
<th scope="row">Max Utilization</th>
|
||||
<td>{{ object.max_utilization }}%</td>
|
||||
</tr>
|
||||
</table>
|
||||
@ -126,7 +126,7 @@
|
||||
{% elif object.cable %}
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<td>Cable</td>
|
||||
<th scope="row">Cable</th>
|
||||
<td>
|
||||
<a href="{{ object.cable.get_absolute_url }}">{{ object.cable }}</a>
|
||||
<a href="{% url 'dcim:powerfeed_trace' pk=object.pk %}" class="btn btn-primary btn-xs" title="Trace">
|
||||
@ -136,27 +136,27 @@
|
||||
</tr>
|
||||
{% if object.connected_endpoint %}
|
||||
<tr>
|
||||
<td>Device</td>
|
||||
<th scope="row">Device</th>
|
||||
<td>
|
||||
<a href="{{ object.connected_endpoint.device.get_absolute_url }}">{{ object.connected_endpoint.device }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<th scope="row">Name</th>
|
||||
<td>
|
||||
<a href="{{ object.connected_endpoint.get_absolute_url }}">{{ object.connected_endpoint.name }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<th scope="row">Type</th>
|
||||
<td>{{ object.connected_endpoint.get_type_display|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<th scope="row">Description</th>
|
||||
<td>{{ object.connected_endpoint.description|placeholder }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Path Status</td>
|
||||
<th scope="row">Path Status</th>
|
||||
<td>
|
||||
{% if object.path.is_active %}
|
||||
<span class="badge bg-success">Reachable</span>
|
||||
@ -169,15 +169,20 @@
|
||||
</table>
|
||||
{% else %}
|
||||
<div class="text-muted">
|
||||
{% if perms.dcim.add_cable %}
|
||||
<a href="{% url 'dcim:powerfeed_connect' termination_a_id=object.pk termination_b_type='power-port' %}?return_url={{ object.get_absolute_url }}" class="btn btn-primary btn-sm pull-right">
|
||||
<span class="mdi mdi-ethernet-cable" aria-hidden="true"></span> Connect
|
||||
</a>
|
||||
{% endif %}
|
||||
Not connected
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if not object.mark_connected and not object.cable %}
|
||||
<div class="card-footer">
|
||||
{% if perms.dcim.add_cable %}
|
||||
<a href="{% url 'dcim:powerfeed_connect' termination_a_id=object.pk termination_b_type='power-port' %}?return_url={{ object.get_absolute_url }}"
|
||||
class="btn btn-primary btn-sm float-end">
|
||||
<i class="mdi mdi-ethernet-cable" aria-hidden="true"></i> Connect
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
|
@ -3,39 +3,41 @@
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{% url 'dcim:powerpanel_list' %}">Power Panels</a></li>
|
||||
<li><a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'dcim:powerpanel_list' %}">Power Panels</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a></li>
|
||||
{% if object.location %}
|
||||
<li><a href="{{ object.location.get_absolute_url }}">{{ object.location }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.location.get_absolute_url }}">{{ object.location }}</a></li>
|
||||
{% endif %}
|
||||
<li>{{ object }}</li>
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Power Panel</strong>
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Power Panel
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">Site</th>
|
||||
<td>
|
||||
<a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Location</th>
|
||||
<td>
|
||||
{% if object.location %}
|
||||
<a href="{{ object.location.get_absolute_url }}">{{ object.location }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<table class="table table-hover panel-body attr-table">
|
||||
<tr>
|
||||
<td>Site</td>
|
||||
<td>
|
||||
<a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Location</td>
|
||||
<td>
|
||||
{% if object.location %}
|
||||
<a href="{{ object.location.get_absolute_url }}">{{ object.location }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
@ -45,7 +47,7 @@
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="row my-3">
|
||||
<div class="col-md-12">
|
||||
{% include 'panel_table.html' with table=powerfeed_table heading='Connected Feeds' %}
|
||||
{% plugin_full_width_page object %}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{% extends base_template %}
|
||||
|
||||
{% block title %}{{ block.super }} - Change Log{% endblock %}
|
||||
{% block title %}{{ object }} - Change Log{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% include 'panel_table.html' %}
|
||||
|
@ -7,8 +7,8 @@
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm btn-outline-secondary"
|
||||
data-toggle="modal"
|
||||
data-target="#docs_modal"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#docs_modal"
|
||||
title="Help"
|
||||
>
|
||||
<i class="bi bi-question"></i>
|
||||
@ -22,15 +22,7 @@
|
||||
{% for field in form.hidden_fields %}{{ field }}{% endfor %}
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-3">
|
||||
{% block tabs %}{% endblock %} {% if form.non_field_errors %}
|
||||
<div class="card bg-danger">
|
||||
<h5 class="card-header">Errors</h5>
|
||||
<div class="card-body">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% block tabs %}{% endblock %}
|
||||
{% block form %}
|
||||
{% if form.Meta.fieldsets %}
|
||||
|
||||
|
@ -3,8 +3,8 @@
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{% url 'ipam:routetarget_list' %}">Route Targets</a></li>
|
||||
<li>{{ object }}</li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'ipam:routetarget_list' %}">Route Targets</a></li>
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -15,23 +15,30 @@
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block tabs %}
|
||||
<ul class="nav nav-tabs" style="margin-bottom: 20px">
|
||||
<li role="presentation"{% if not active_tab %} class="active"{% endif %}>
|
||||
<a href="{% url 'ipam:vlan' pk=object.pk %}">VLAN</a>
|
||||
</li>
|
||||
<li role="presentation"{% if active_tab == 'interfaces' %} class="active"{% endif %}>
|
||||
<a href="{% url 'ipam:vlan_interfaces' pk=object.pk %}">Device Interfaces <span class="badge">{{ object.get_interfaces.count }}</span></a>
|
||||
</li>
|
||||
<li role="presentation"{% if active_tab == 'vminterfaces' %} class="active"{% endif %}>
|
||||
<a href="{% url 'ipam:vlan_vminterfaces' pk=object.pk %}">VM Interfaces <span class="badge">{{ object.get_vminterfaces.count }}</span></a>
|
||||
</li>
|
||||
{% if perms.extras.view_objectchange %}
|
||||
<li role="presentation"{% if active_tab == 'changelog' %} class="active"{% endif %}>
|
||||
<a href="{% url 'ipam:vlan_changelog' pk=object.pk %}">Change Log</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
{% block tab_items %}
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link{% if not active_tab %} active{% endif %}" href="{% url 'ipam:vlan' pk=object.pk %}">VLAN</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link{% if active_tab == 'interfaces' %} active{% endif %}" href="{% url 'ipam:vlan_interfaces' pk=object.pk %}">
|
||||
Device Interfaces
|
||||
{% with count=object.get_interfaces.count %}
|
||||
{% if count > 0 %}
|
||||
<span class="badge bg-primary">{{ count }}</span>
|
||||
{% endif %}
|
||||
{% endwith %}
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<a class="nav-link{% if active_tab == 'vminterfaces' %} active{% endif %}" href="{% url 'ipam:vlan_vminterfaces' pk=object.pk %}">
|
||||
VM Interfaces
|
||||
{% comment %} {% with count=object.get_vminterfaces.count %}
|
||||
{% if count > 0 %}
|
||||
<span class="badge bg-primary">{{ count }}</span>
|
||||
{% endif %}
|
||||
{% endwith %} {% endcomment %}
|
||||
</a>
|
||||
</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
@ -44,7 +51,12 @@
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<td>Site</td>
|
||||
<td colspan="2">
|
||||
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Site</th>
|
||||
<td>
|
||||
{% if object.site %}
|
||||
{% if object.site.region %}
|
||||
@ -57,7 +69,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Group</td>
|
||||
<th scope="row">Group</th>
|
||||
<td>
|
||||
{% if object.group %}
|
||||
<a href="{{ object.group.get_absolute_url }}">{{ object.group }}</a>
|
||||
@ -67,15 +79,15 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>VLAN ID</td>
|
||||
<th scope="row">VLAN ID</th>
|
||||
<td>{{ object.vid }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<th scope="row">Name</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tenant</td>
|
||||
<th scope="row">Tenant</th>
|
||||
<td>
|
||||
{% if object.tenant %}
|
||||
{% if object.tenant.group %}
|
||||
@ -88,13 +100,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Status</td>
|
||||
<td>
|
||||
<span class="badge bg-{{ object.get_status_class }}">{{ object.get_status_display }}</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Role</td>
|
||||
<th scope="row">Role</th>
|
||||
<td>
|
||||
{% if object.role %}
|
||||
<a href="{% url 'ipam:vlan_list' %}?role={{ object.role.slug }}">{{ object.role }}</a>
|
||||
@ -104,7 +110,7 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Description</td>
|
||||
<th scope="row">Description</th>
|
||||
<td>{{ object.description|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@ -3,25 +3,45 @@
|
||||
{% load helpers %}
|
||||
|
||||
{% block form %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>VLAN Group</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_field form.name %}
|
||||
{% render_field form.slug %}
|
||||
{% render_field form.description %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>VLAN Group</h4>
|
||||
{% render_field form.name %}
|
||||
{% render_field form.slug %}
|
||||
{% render_field form.description %}
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Scope</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% with virtual_tab_active=form.initial.cluster %}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation"{% if not virtual_tab_active %} class="active"{% endif %}><a href="#physical" role="tab" data-toggle="tab">Physical</a></li>
|
||||
<li role="presentation"{% if virtual_tab_active %} class="active"{% endif %}><a href="#virtual" role="tab" data-toggle="tab">Virtual</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="field-group">
|
||||
<h4>Scope</h4>
|
||||
{% with virtual_tab_active=form.initial.cluster %}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
role="tab"
|
||||
type="button"
|
||||
id="physical_tab"
|
||||
data-bs-toggle="tab"
|
||||
aria-controls="physical"
|
||||
data-bs-target="#physical"
|
||||
class="nav-link {% if not virtual_tab_active %}active{% endif %}"
|
||||
>
|
||||
Physical
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
role="tab"
|
||||
type="button"
|
||||
id="virtual_tab"
|
||||
data-bs-toggle="tab"
|
||||
aria-controls="virtual"
|
||||
data-bs-target="#virtual"
|
||||
class="nav-link {% if virtual_tab_active %}active{% endif %}"
|
||||
>
|
||||
Virtual
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="card my-3">
|
||||
<div class="card-body tab-content">
|
||||
<div class="tab-pane{% if not virtual_tab_active %} active{% endif %}" id="physical">
|
||||
{% render_field form.region %}
|
||||
{% render_field form.site_group %}
|
||||
@ -33,17 +53,15 @@
|
||||
{% render_field form.cluster_group %}
|
||||
{% render_field form.cluster %}
|
||||
</div>
|
||||
<span class="form-text">The VLAN group will be limited in scope to the most-specific object selected above.</span>
|
||||
</div>
|
||||
<span class="help-block">The VLAN group will be limited in scope to the most-specific object selected above.</span>
|
||||
{% endwith %}
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
</div>
|
||||
{% if form.custom_fields %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Custom Fields</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_custom_fields form %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>Custom Fields</h4>
|
||||
{% render_custom_fields form %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
@ -1,24 +1,41 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'generic/object.html' %}
|
||||
|
||||
{% block title %}{{ object }} - VLANs{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row noprint">
|
||||
<div class="col-sm-12 col-md-12">
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{% url 'ipam:vlangroup_list' %}">VLAN Groups</a></li>
|
||||
{% if object.site %}
|
||||
<li><a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a></li>
|
||||
{% endif %}
|
||||
<li>{{ object }}</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'ipam/inc/vlangroup_header.html' %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% include 'utilities/obj_table.html' with table=vlan_table table_template='panel_table.html' heading='VLANs' bulk_edit_url='ipam:vlan_bulk_edit' bulk_delete_url='ipam:vlan_bulk_delete' %}
|
||||
</div>
|
||||
</div>
|
||||
{% block controls %}
|
||||
{% if perms.ipam.add_vlan and first_available_vlan %}
|
||||
<a
|
||||
href="{% url 'ipam:vlan_add' %}?vid={{ first_available_vlan }}&group={{ object.pk }}{% if object.site %}&site={{ object.site.pk }}{% endif %}"
|
||||
class="btn btn-sm btn-success m-1">
|
||||
<i class="bi bi-plus" aria-hidden="true"></i> Add a VLAN
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if perms.ipam.change_vlangroup %}
|
||||
<a
|
||||
href="{% url 'ipam:vlangroup_edit' pk=object.pk %}"
|
||||
class="btn btn-sm btn-warning m-1">
|
||||
<i class="mdi mdi-pencil" aria-hidden="true"></i> Edit this VLAN Group
|
||||
</a>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{% url 'ipam:vlangroup_list' %}">VLAN Groups</a>
|
||||
</li>
|
||||
{% if object.site %}
|
||||
<li class="breadcrumb-item">
|
||||
<a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% include 'utilities/obj_table.html' with table=vlan_table table_template='panel_table.html' heading='VLANs' bulk_edit_url='ipam:vlan_bulk_edit' bulk_delete_url='ipam:vlan_bulk_delete' %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
@ -7,8 +7,8 @@
|
||||
{% block title %}VRF {{ object }}{% endblock %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{% url 'ipam:vrf_list' %}">VRFs</a></li>
|
||||
<li>{{ object }}</li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'ipam:vrf_list' %}">VRFs</a></li>
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -15,11 +15,12 @@
|
||||
<a class="text-decoration-none" href="{% url 'admin:index' %}">
|
||||
<i class="bi bi-gear-wide-connected"></i> Admin
|
||||
</a>
|
||||
{% else %}
|
||||
{% endif %}
|
||||
</li>
|
||||
<li class="dropdown-item">
|
||||
<a class="text-decoration-none" href="{% url 'user:profile' %}">
|
||||
<i class="bi bi-person-fill"></i> Profile
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
<li><hr class="dropdown-divider" /></li>
|
||||
<li class="dropdown-item">
|
||||
|
@ -5,54 +5,47 @@
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{% url 'secrets:secret_list' %}">Secrets</a></li>
|
||||
<li><a href="{% url 'secrets:secret_list' %}?role={{ object.role.slug }}">{{ object.role }}</a></li>
|
||||
<li><a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a></li>
|
||||
<li>{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block buttons %}
|
||||
{% if perms.secrets.change_secret %}
|
||||
{% edit_button object %}
|
||||
{% endif %}
|
||||
{% if perms.secrets.delete_secret %}
|
||||
{% delete_button object %}
|
||||
{% endif %}
|
||||
<li class="breadcrumb-item"><a href="{% url 'secrets:secret_list' %}">Secrets</a></li>
|
||||
<li class="breadcrumb-item"><a href="{% url 'secrets:secret_list' %}?role={{ object.role.slug }}">{{ object.role }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a></li>
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Secret Attributes</strong>
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Secret Attributes
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover">
|
||||
<tr>
|
||||
<th scope="row">Assigned object</th>
|
||||
<td>
|
||||
<a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Role</th>
|
||||
<td>{{ object.role }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Name</th>
|
||||
<td>{{ object.name|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<table class="table table-hover panel-body">
|
||||
<tr>
|
||||
<td>Assigned object</td>
|
||||
<td>
|
||||
<a href="{{ object.assigned_object.get_absolute_url }}">{{ object.assigned_object }}</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Role</td>
|
||||
<td>{{ object.role }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>{{ object.name|placeholder }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/custom_fields_panel.html' %}
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Secret Data</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Secret Data
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<form id="secret_form">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
@ -60,13 +53,13 @@
|
||||
<div class="col-md-2">Secret</div>
|
||||
<div class="col-md-6" id="secret_{{ object.pk }}">********</div>
|
||||
<div class="col-md-4 text-right noprint">
|
||||
<button class="btn btn-xs btn-success unlock-secret" secret-id="{{ object.pk }}">
|
||||
<button class="btn btn-sm btn-success unlock-secret" secret-id="{{ object.pk }}">
|
||||
<i class="mdi mdi-lock"></i> Unlock
|
||||
</button>
|
||||
<button class="btn btn-xs btn-default copy-secret collapse" secret-id="{{ object.pk }}" data-clipboard-target="#secret_{{ object.pk }}">
|
||||
<button class="btn btn-sm btn-default copy-secret collapse" secret-id="{{ object.pk }}" data-clipboard-target="#secret_{{ object.pk }}">
|
||||
<i class="mdi mdi-content-copy"></i> Copy
|
||||
</button>
|
||||
<button class="btn btn-xs btn-danger lock-secret collapse" secret-id="{{ object.pk }}">
|
||||
<button class="btn btn-sm btn-danger lock-secret collapse" secret-id="{{ object.pk }}">
|
||||
<i class="mdi mdi-lock-open"></i> Lock
|
||||
</button>
|
||||
</div>
|
||||
@ -85,7 +78,3 @@
|
||||
|
||||
{% include 'secrets/inc/private_key_modal.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="{% static 'js/secrets.js' %}?v{{ settings.VERSION }}"></script>
|
||||
{% endblock %}
|
||||
|
@ -1,99 +1,88 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
{% load static %}
|
||||
{% load form_helpers %}
|
||||
|
||||
{% block content %}
|
||||
<form action="." method="post" class="form form-horizontal">
|
||||
{% csrf_token %}
|
||||
{{ form.private_key }}
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h3>{% block title %}{% if obj.pk %}Editing {{ obj }}{% else %}Add a Secret{% endif %}{% endblock %}</h3>
|
||||
{% if form.non_field_errors %}
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading"><strong>Errors</strong></div>
|
||||
<div class="panel-body">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Secret Assignment</strong>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
{% with vm_tab_active=form.initial.virtual_machine %}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation"{% if not vm_tab_active %} class="active"{% endif %}><a href="#device" role="tab" data-toggle="tab">Device</a></li>
|
||||
<li role="presentation"{% if vm_tab_active %} class="active"{% endif %}><a href="#virtualmachine" role="tab" data-toggle="tab">Virtual Machine</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane{% if not vm_tab_active %} active{% endif %}" id="device">
|
||||
{% render_field form.device %}
|
||||
</div>
|
||||
<div class="tab-pane{% if vm_tab_active %} active{% endif %}" id="virtualmachine">
|
||||
{% render_field form.virtual_machine %}
|
||||
</div>
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% render_field form.role %}
|
||||
{% render_field form.name %}
|
||||
{% render_field form.userkeys %}
|
||||
{% render_field form.tags %}
|
||||
</div>
|
||||
{% block title %}{% if obj.pk %}Editing {{ obj }}{% else %}Add a Secret{% endif %}{% endblock %}
|
||||
|
||||
{% block form %}
|
||||
{% render_errors form %}
|
||||
|
||||
|
||||
{{ form.private_key }}
|
||||
<div class="field-group">
|
||||
<h4>Secret Assignment</h4>
|
||||
<ul class="nav nav-tabs mb-3" role="tablist">
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
role="tab"
|
||||
type="button"
|
||||
id="device_tab"
|
||||
data-bs-toggle="tab"
|
||||
class="nav-link{% if not vm_tab_active %} active{% endif %}"
|
||||
data-bs-target="#device"
|
||||
aria-controls="device"
|
||||
>
|
||||
Device
|
||||
</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button
|
||||
role="tab"
|
||||
type="button"
|
||||
id="vm_tab"
|
||||
data-bs-toggle="tab"
|
||||
class="nav-link{% if vm_tab_active %} active{% endif %}"
|
||||
data-bs-target="#virtualmachine"
|
||||
aria-controls="virtualmachine"
|
||||
>
|
||||
Virtual Machine
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
{% with vm_tab_active=form.initial.virtual_machine %}
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane{% if not vm_tab_active %} active{% endif %}" id="device">
|
||||
{% render_field form.device %}
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Secret Data</strong></div>
|
||||
<div class="panel-body">
|
||||
{% if obj.pk %}
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label required">Current Plaintext</label>
|
||||
<div class="col-md-7">
|
||||
<p class="form-control-static" id="secret_{{ obj.pk }}">********</p>
|
||||
</div>
|
||||
<div class="col-md-2 text-right">
|
||||
<button class="btn btn-xs btn-success unlock-secret" secret-id="{{ obj.pk }}">
|
||||
<i class="mdi mdi-lock"></i> Unlock
|
||||
</button>
|
||||
<button class="btn btn-xs btn-danger lock-secret collapse" secret-id="{{ obj.pk }}">
|
||||
<i class="mdi mdi-lock-open"></i> Lock
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% render_field form.plaintext %}
|
||||
{% render_field form.plaintext2 %}
|
||||
</div>
|
||||
<div class="tab-pane{% if vm_tab_active %} active{% endif %}" id="virtualmachine">
|
||||
{% render_field form.virtual_machine %}
|
||||
</div>
|
||||
{% if form.custom_fields %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Custom Fields</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_custom_fields form %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endwith %}
|
||||
{% render_field form.role %}
|
||||
{% render_field form.name %}
|
||||
{% render_field form.userkeys %}
|
||||
{% render_field form.tags %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>Secret Data</h4>
|
||||
{% if obj.pk %}
|
||||
<div class="form-floating mb-3">
|
||||
<input class="form-control" value="********" id="secret_{{ obj.pk }}" />
|
||||
<label class="required">Current Plain Text</label>
|
||||
</div>
|
||||
<div class="col-md-2 text-end">
|
||||
<button class="btn btn-sm btn-success unlock-secret" data-secret-id="{{ obj.pk }}">
|
||||
<i class="mdi mdi-lock"></i> Unlock
|
||||
</button>
|
||||
<button class="btn btn-sm, btn-danger lock-secret collapse" data-secret-id="{{ obj.pk }}">
|
||||
<i class="mdi mdi-lock-open"></i> Lock
|
||||
</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% render_field form.plaintext %}
|
||||
{% render_field form.plaintext2 %}
|
||||
|
||||
</div>
|
||||
{% if form.custom_fields %}
|
||||
<div class="card">
|
||||
<h5 class="card-header">Custom Fields</h5>
|
||||
<div class="card-body">
|
||||
{% render_custom_fields form %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="col-md-12 text-center">
|
||||
{% if obj.pk %}
|
||||
<button type="submit" name="_update" class="btn btn-primary">Update</button>
|
||||
<a href="{% url 'secrets:secret' pk=obj.pk %}" class="btn btn-default">Cancel</a>
|
||||
{% else %}
|
||||
<button type="submit" name="_create" class="btn btn-primary">Create</button>
|
||||
<button type="submit" name="_addanother" class="btn btn-primary">Create and Add Another</button>
|
||||
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
|
||||
{% include 'secrets/inc/private_key_modal.html' %}
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="{% static 'js/secrets.js' %}?v{{ settings.VERSION }}"></script>
|
||||
{% endblock %}
|
||||
|
@ -7,15 +7,15 @@
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{% for token in tokens %}
|
||||
<div class="panel panel-{% if token.is_expired %}danger{% else %}default{% endif %}">
|
||||
<div class="panel-heading">
|
||||
<div class="pull-right noprint">
|
||||
<a class="btn btn-xs btn-success copy-token" data-clipboard-target="#token_{{ token.pk }}">Copy</a>
|
||||
<div class="card{% if token.is_expired %} bg-danger{% endif %}">
|
||||
<div class="card-header">
|
||||
<div class="float-end noprint">
|
||||
<a class="m-1 btn btn-sm btn-success copy-token" data-clipboard-target="#token_{{ token.pk }}">Copy</a>
|
||||
{% if perms.users.change_token %}
|
||||
<a href="{% url 'user:token_edit' pk=token.pk %}" class="btn btn-xs btn-warning">Edit</a>
|
||||
<a href="{% url 'user:token_edit' pk=token.pk %}" class="m-1 btn btn-sm btn-warning">Edit</a>
|
||||
{% endif %}
|
||||
{% if perms.users.delete_token %}
|
||||
<a href="{% url 'user:token_delete' pk=token.pk %}" class="btn btn-xs btn-danger">Delete</a>
|
||||
<a href="{% url 'user:token_delete' pk=token.pk %}" class="m-1 btn btn-sm btn-danger">Delete</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<i class="mdi mdi-key"></i>
|
||||
@ -24,7 +24,7 @@
|
||||
<span class="label label-danger">Expired</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<div class="card-body">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<small class="text-muted">Created</small><br />
|
||||
@ -55,22 +55,20 @@
|
||||
{% empty %}
|
||||
<p>You do not have any API tokens.</p>
|
||||
{% endfor %}
|
||||
{% if perms.users.add_token %}
|
||||
<a href="{% url 'user:token_add' %}" class="btn btn-primary">
|
||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span>
|
||||
Add a token
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="alert alert-info text-center" role="alert">
|
||||
You do not have permission to create new API tokens. If needed, ask an administrator to enable token creation for your account or an assigned group.
|
||||
<div class="row my-3">
|
||||
<div class="col-md-12">
|
||||
{% if perms.users.add_token %}
|
||||
<a href="{% url 'user:token_add' %}" class="btn btn-primary">
|
||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span>
|
||||
Add a Token
|
||||
</a>
|
||||
{% else %}
|
||||
<div class="alert alert-info text-center" role="alert">
|
||||
You do not have permission to create new API tokens. If needed, ask an administrator to enable token creation for your account or an assigned group.
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script type="text/javascript">
|
||||
new ClipboardJS('.copy-token');
|
||||
</script>
|
||||
{% endblock %}
|
||||
|
@ -1,34 +1,21 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'layout.html' %}
|
||||
|
||||
{% block title %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-10 col-md-offset-1">
|
||||
<h1>{% block title %}{% endblock %}</h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-md-2 col-md-offset-1">
|
||||
<ul class="nav nav-pills nav-stacked">
|
||||
<li{% if active_tab == "profile" %} class="active"{% endif %}>
|
||||
<a href="{% url 'user:profile' %}">Profile</a>
|
||||
</li>
|
||||
<li{% if active_tab == "preferences" %} class="active"{% endif %}>
|
||||
<a href="{% url 'user:preferences' %}">Preferences</a>
|
||||
</li>
|
||||
<div class="col-sm-3 col-md-2 col-md-offset-1 border-end">
|
||||
<nav class="nav nav-pills nav-justified flex-column">
|
||||
<a class="nav-item nav-link text-start{% if active_tab == 'profile' %} active{% endif %}" href="{% url 'user:profile' %}">Profile</a>
|
||||
<a class="nav-link nav-item text-start{% if active_tab == 'preferences' %} active{% endif %}" href="{% url 'user:preferences' %}">Preferences</a>
|
||||
{% if not request.user.ldap_username %}
|
||||
<li{% if active_tab == "change_password" %} class="active"{% endif %}>
|
||||
<a href="{% url 'user:change_password' %}">Change Password</a>
|
||||
</li>
|
||||
<a class="nav-link nav-item text-start{% if active_tab == 'change-password' %} active{% endif %}" href="{% url 'user:change_password' %}">Change Password</a>
|
||||
{% endif %}
|
||||
<li{% if active_tab == "api_tokens" %} class="active"{% endif %}>
|
||||
<a href="{% url 'user:token_list' %}">API Tokens</a>
|
||||
</li>
|
||||
<li{% if active_tab == "userkey" %} class="active"{% endif %}>
|
||||
<a href="{% url 'user:userkey' %}">User Key</a>
|
||||
</li>
|
||||
</ul>
|
||||
<a class="nav-link nav-item text-start{% if active_tab == 'api-tokens' %} active{% endif %}" href="{% url 'user:token_list' %}">API Tokens</a>
|
||||
<a class="nav-link nav-item text-start{% if active_tab == 'userkey' %} active{% endif %}" href="{% url 'user:userkey' %}">User Key</a>
|
||||
</nav>
|
||||
</div>
|
||||
<div class="col-sm-9 col-md-8">
|
||||
<div class="col-sm-9 col-md-8 px-4">
|
||||
{% block usercontent %}{% endblock %}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -3,28 +3,20 @@
|
||||
|
||||
{% block title %}Change Password{% endblock %}
|
||||
|
||||
{% render_errors form %}
|
||||
|
||||
{% block usercontent %}
|
||||
<form action="." method="post" class="form form-horizontal col-md-10 col-md-offset-1">
|
||||
{% csrf_token %}
|
||||
{% if form.non_field_errors %}
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading"><strong>Errors</strong></div>
|
||||
<div class="panel-body">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Password</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_field form.old_password %}
|
||||
{% render_field form.new_password1 %}
|
||||
{% render_field form.new_password2 %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>Password</h4>
|
||||
{% render_field form.old_password %}
|
||||
{% render_field form.new_password1 %}
|
||||
{% render_field form.new_password2 %}
|
||||
</div>
|
||||
<div class="text-right">
|
||||
<div class="text-end">
|
||||
<a href="{% url 'user:profile' %}" class="btn btn-outline-danger">Cancel</a>
|
||||
<button type="submit" name="_update" class="btn btn-primary">Update</button>
|
||||
<a href="{% url 'user:profile' %}" class="btn btn-default">Cancel</a>
|
||||
</div>
|
||||
</form>
|
||||
{% endblock %}
|
||||
|
@ -4,16 +4,34 @@
|
||||
{% block title %}User Profile{% endblock %}
|
||||
|
||||
{% block usercontent %}
|
||||
<small class="text-muted">User login</small>
|
||||
<small class="text-muted">User Login</small>
|
||||
<h5>{{ request.user.username }}</h5>
|
||||
<small class="text-muted">Full name</small>
|
||||
<h5>{{ request.user.first_name }} {{ request.user.last_name }}</h5>
|
||||
<small class="text-muted">Full Name</small>
|
||||
<h5>
|
||||
{% if request.user.first_name and request.user.last_name %}
|
||||
{{ request.user.first_name }} {{ request.user.last_name }}
|
||||
{% elif request.user.first_name and not request.user.last_name %}
|
||||
{{ request.user.first_name }}
|
||||
{% elif request.user.last_name and not request.user.first_name %}
|
||||
{{ request.user.last_name }}
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
<small class="text-muted">Email</small>
|
||||
<h5>{{ request.user.email }}</h5>
|
||||
<small class="text-muted">Registered</small>
|
||||
<h5>{{ request.user.date_joined }}</h5>
|
||||
<small class="text-muted">Groups</small>
|
||||
<h5>{{ request.user.groups.all|join:', ' }}</h5>
|
||||
<small class="text-muted">Admin access</small>
|
||||
<h5>
|
||||
{% if request.user.groups.all %}
|
||||
{% for group in request.user.groups.all %}
|
||||
<span class="badge bg-secondary">{{ group }}</span>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</h5>
|
||||
<small class="text-muted">Admin Access</small>
|
||||
<h5>{{ request.user.is_staff|yesno|capfirst }}</h5>
|
||||
{% endblock %}
|
||||
|
@ -4,18 +4,18 @@
|
||||
|
||||
{% block usercontent %}
|
||||
{% if object %}
|
||||
<div class="pull-right noprint">
|
||||
<div class="float-end noprint">
|
||||
<a href="{% url 'user:userkey_edit' %}" class="btn btn-warning">
|
||||
<span class="mdi mdi-pencil" aria-hidden="true"></span>
|
||||
Edit user key
|
||||
Edit User Key
|
||||
</a>
|
||||
</div>
|
||||
<h4>
|
||||
Your user key is:
|
||||
Your user key is
|
||||
{% if object.is_active %}
|
||||
<span class="label label-success">Active</span>
|
||||
<span class="badge bg-success">Active</span>
|
||||
{% else %}
|
||||
<span class="label label-danger">Inactive</span>
|
||||
<span class="badge bg-danger">Inactive</span>
|
||||
{% endif %}
|
||||
</h4>
|
||||
{% include 'inc/created_updated.html' %}
|
||||
@ -25,7 +25,7 @@
|
||||
Your user key is inactive. Ask an administrator to enable it for you.
|
||||
</div>
|
||||
{% endif %}
|
||||
<pre>{{ object.public_key }}</pre>
|
||||
<pre class="border rounded p-3 copyable">{{ object.public_key }}</pre>
|
||||
<hr />
|
||||
{% if object.session_key %}
|
||||
<div class="pull-right noprint">
|
||||
|
@ -13,48 +13,43 @@
|
||||
{% endif %}
|
||||
<form action="." method="post" class="form">
|
||||
{% csrf_token %}
|
||||
<div class="form-group">
|
||||
<div class="field-group">
|
||||
{% render_field form.public_key %}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group">
|
||||
<div class="col-sm-6 col-md-6">
|
||||
<button type="button" class="btn btn-info" id="generate_keypair">Generate a New Key Pair</button>
|
||||
</div>
|
||||
<div class="col-sm-6 col-md-6 text-right">
|
||||
<button type="submit" name="_update" class="btn btn-primary">Save</button>
|
||||
<a href="{% url 'user:userkey' %}" class="btn btn-default">Cancel</a>
|
||||
</div>
|
||||
<div class="row my-3">
|
||||
<div class="col-4 text-start">
|
||||
<button type="button" class="btn btn-info" id="generate_keypair" data-bs-toggle="modal" data-bs-target="#new_keypair_modal">Generate a New Key Pair</button>
|
||||
</div>
|
||||
<div class="col-8 text-end">
|
||||
<a href="{% url 'user:userkey' %}" class="btn btn-outline-danger">Cancel</a>
|
||||
<button type="submit" name="_update" class="btn btn-primary">Save</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div class="modal fade" id="new_keypair_modal" tabindex="-1" role="dialog">
|
||||
<div class="modal-dialog modal-md" role="document">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title" id="new_keypair_modal_title">
|
||||
New RSA Key Pair
|
||||
</h4>
|
||||
<button type="button" class="btn btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<strong>New Public Key</strong>
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" id="new_pubkey" style="height: 250px;"></textarea>
|
||||
<div class="field-group">
|
||||
<h5>New Public Key</h5>
|
||||
<textarea class="form-control" rows="10" id="new_pubkey" style="height: 250px;font-family:var(--bs-font-monospace);"></textarea>
|
||||
</div>
|
||||
<strong>New Private Key</strong>
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" id="new_privkey" style="height: 250px;"></textarea>
|
||||
|
||||
<div class="field-group">
|
||||
<h5>New Private Key</h5>
|
||||
<textarea class="form-control" rows="10" id="new_privkey" style="height: 250px;font-family:var(--bs-font-monospace);"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer text-center">
|
||||
<button type="button" class="btn btn-danger" id="use_new_pubkey" data-dismiss="modal">I have saved my new private key</button>
|
||||
<button type="button" class="btn btn-danger" id="use_new_pubkey" data-bs-dismiss="modal">I Saved My New Private Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block javascript %}
|
||||
<script src="{% static 'js/secrets.js' %}?v{{ settings.VERSION }}"></script>
|
||||
{% endblock %}
|
||||
|
@ -4,11 +4,11 @@
|
||||
{% if form.errors or form.non_field_errors %}
|
||||
<div class="alert alert-danger mt-3" role="alert">
|
||||
<h4 class="alert-heading">Errors</h4>
|
||||
{% if form.errors %}
|
||||
<hr />
|
||||
{% if form.errors and '__all__' not in form.errors %}
|
||||
<hr />
|
||||
{% endif %}
|
||||
<div class="ps-2">
|
||||
{% if form.errors %}
|
||||
{% if form.errors and '__all__' not in form.errors %}
|
||||
{% for field_name, errors in form.errors.items %}
|
||||
{% if not field_name|startswith:'__' %}
|
||||
{% with field=form|getfield:field_name %}
|
||||
|
@ -5,72 +5,74 @@
|
||||
{% load plugins %}
|
||||
|
||||
{% block breadcrumbs %}
|
||||
<li><a href="{{ object.type.get_absolute_url }}">{{ object.type }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.type.get_absolute_url }}">{{ object.type }}</a></li>
|
||||
{% if object.group %}
|
||||
<li><a href="{{ object.group.get_absolute_url }}">{{ object.group }}</a></li>
|
||||
<li class="breadcrumb-item"><a href="{{ object.group.get_absolute_url }}">{{ object.group }}</a></li>
|
||||
{% endif %}
|
||||
<li>{{ object }}</li>
|
||||
<li class="breadcrumb-item">{{ object }}</li>
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Cluster</strong>
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Cluster
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
<table class="table table-hover attr-table">
|
||||
<tr>
|
||||
<th scope="row">Name</th>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Type</th>
|
||||
<td><a href="{{ object.type.get_absolute_url }}">{{ object.type }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Group</th>
|
||||
<td>
|
||||
{% if object.group %}
|
||||
<a href="{{ object.group.get_absolute_url }}">{{ object.group }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Tenant</th>
|
||||
<td>
|
||||
{% if object.tenant %}
|
||||
<a href="{{ object.tenant.get_absolute_url }}">{{ object.tenant }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Site</th>
|
||||
<td>
|
||||
{% if object.site %}
|
||||
<a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th scope="row">Virtual Machines</th>
|
||||
<td><a href="{% url 'virtualization:virtualmachine_list' %}?cluster_id={{ object.pk }}">{{ object.virtual_machines.count }}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<table class="table table-hover panel-body attr-table">
|
||||
<tr>
|
||||
<td>Name</td>
|
||||
<td>{{ object.name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Type</td>
|
||||
<td><a href="{{ object.type.get_absolute_url }}">{{ object.type }}</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Group</td>
|
||||
<td>
|
||||
{% if object.group %}
|
||||
<a href="{{ object.group.get_absolute_url }}">{{ object.group }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Tenant</td>
|
||||
<td>
|
||||
{% if object.tenant %}
|
||||
<a href="{{ object.tenant.get_absolute_url }}">{{ object.tenant }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Site</td>
|
||||
<td>
|
||||
{% if object.site %}
|
||||
<a href="{{ object.site.get_absolute_url }}">{{ object.site }}</a>
|
||||
{% else %}
|
||||
<span class="text-muted">None</span>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Virtual Machines</td>
|
||||
<td><a href="{% url 'virtualization:virtualmachine_list' %}?cluster_id={{ object.pk }}">{{ object.virtual_machines.count }}</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
{% include 'inc/custom_fields_panel.html' %}
|
||||
{% include 'extras/inc/tags_panel.html' with tags=object.tags.all url='virtualization:cluster_list' %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Comments</strong>
|
||||
</div>
|
||||
<div class="panel-body rendered-markdown">
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Comments
|
||||
</h5>
|
||||
<div class="card-body rendered-markdown">
|
||||
{% if object.comments %}
|
||||
{{ object.comments|render_markdown }}
|
||||
{% else %}
|
||||
@ -81,30 +83,30 @@
|
||||
{% plugin_left_page object %}
|
||||
</div>
|
||||
<div class="col-md-7">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<strong>Host Devices</strong>
|
||||
</div>
|
||||
{% if perms.virtualization.change_cluster %}
|
||||
<div class="card">
|
||||
<h5 class="card-header">
|
||||
Host Devices
|
||||
</h5>
|
||||
<div class="card-body">
|
||||
{% if perms.virtualization.change_cluster %}
|
||||
<form action="{% url 'virtualization:cluster_remove_devices' pk=object.pk %}" method="post">
|
||||
{% csrf_token %}
|
||||
{% endif %}
|
||||
{% include 'responsive_table.html' with table=device_table %}
|
||||
{% if perms.virtualization.change_cluster %}
|
||||
<div class="panel-footer noprint">
|
||||
<div class="pull-right">
|
||||
<a href="{% url 'virtualization:cluster_add_devices' pk=object.pk %}?site={{ object.site.pk }}" class="btn btn-primary btn-xs">
|
||||
{% csrf_token %}
|
||||
{% include 'responsive_table.html' with table=device_table %}
|
||||
{% if perms.virtualization.change_cluster %}
|
||||
<div class="card-footer noprint justify-content-between d-flex">
|
||||
<button type="submit" name="_remove" class="btn btn-danger primary btn-sm">
|
||||
<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span>
|
||||
Remove devices
|
||||
</button>
|
||||
<a href="{% url 'virtualization:cluster_add_devices' pk=object.pk %}?site={{ object.site.pk }}" class="btn btn-primary btn-sm">
|
||||
<span class="mdi mdi-plus-thick" aria-hidden="true"></span>
|
||||
Add devices
|
||||
</a>
|
||||
</div>
|
||||
<button type="submit" name="_remove" class="btn btn-danger primary btn-xs">
|
||||
<span class="mdi mdi-trash-can-outline" aria-hidden="true"></span>
|
||||
Remove devices
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% plugin_right_page object %}
|
||||
</div>
|
||||
|
@ -1,36 +1,29 @@
|
||||
{% extends 'base.html' %}
|
||||
{% extends 'generic/object_edit.html' %}
|
||||
{% load static %}
|
||||
{% load form_helpers %}
|
||||
|
||||
{% render_errors form %}
|
||||
|
||||
{% block title %}Add Device to Cluster {{ cluster }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<form action="." method="post" class="form form-horizontal">
|
||||
<form action="." method="post">
|
||||
{% csrf_token %}
|
||||
{% for field in form.hidden_fields %}
|
||||
{{ field }}
|
||||
{% endfor %}
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3">
|
||||
<h3>{% block title %}Add Devices to Cluster {{ cluster }}{% endblock %}</h3>
|
||||
{% if form.non_field_errors %}
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading"><strong>Errors</strong></div>
|
||||
<div class="panel-body">
|
||||
{{ form.non_field_errors }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Device Selection</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_form form %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>Device Selection</h4>
|
||||
{% render_form form %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-md-offset-3 text-right noprint">
|
||||
<div class="col-md-6 col-md-offset-3 text-end noprint">
|
||||
<a href="{{ return_url }}" class="btn btn-outline-danger">Cancel</a>
|
||||
<button type="submit" name="_add" class="btn btn-primary">Add Devices</button>
|
||||
<a href="{{ return_url }}" class="btn btn-default">Cancel</a>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -2,41 +2,37 @@
|
||||
{% load form_helpers %}
|
||||
|
||||
{% block form %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Interface</strong></div>
|
||||
<div class="panel-body">
|
||||
{% if form.instance.virtual_machine %}
|
||||
<div class="form-group">
|
||||
<label class="col-md-3 control-label required" for="id_device">Virtual Machine</label>
|
||||
<div class="col-md-9">
|
||||
<p class="form-control-static">
|
||||
<a href="{{ form.instance.virtual_machine.get_absolute_url }}">{{ form.instance.virtual_machine }}</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% render_field form.name %}
|
||||
{% render_field form.enabled %}
|
||||
{% render_field form.mac_address %}
|
||||
{% render_field form.mtu %}
|
||||
{% render_field form.description %}
|
||||
{% render_field form.tags %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>Interface</h4>
|
||||
{% if form.instance.virtual_machine %}
|
||||
<div class="form-floating">
|
||||
<input class="form-control" value="{{ form.instance.virtual_machine }}"/>
|
||||
{% comment %} <div class="col-md-9">
|
||||
<p class="form-control-static">
|
||||
<a href="{{ form.instance.virtual_machine.get_absolute_url }}">{{ form.instance.virtual_machine }}</a>
|
||||
</p>
|
||||
</div> {% endcomment %}
|
||||
<label class="col-md-3 control-label required" for="id_device">Virtual Machine</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% render_field form.name %}
|
||||
{% render_field form.enabled %}
|
||||
{% render_field form.mac_address %}
|
||||
{% render_field form.mtu %}
|
||||
{% render_field form.description %}
|
||||
{% render_field form.tags %}
|
||||
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>802.1Q Switching</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_field form.mode %}
|
||||
{% render_field form.untagged_vlan %}
|
||||
{% render_field form.tagged_vlans %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>802.1Q Switching</h4>
|
||||
{% render_field form.mode %}
|
||||
{% render_field form.untagged_vlan %}
|
||||
{% render_field form.tagged_vlans %}
|
||||
</div>
|
||||
{% if form.custom_fields %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Custom Fields</strong></div>
|
||||
<div class="panel-body">
|
||||
{% render_custom_fields form %}
|
||||
</div>
|
||||
<div class="field-group">
|
||||
<h4>Custom Fields</h4>
|
||||
{% render_custom_fields form %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
Reference in New Issue
Block a user