implement layout changes

This commit is contained in:
checktheroads 2021-03-13 02:20:50 -07:00
parent 9b89afd6dc
commit 1d9e55ca6e
7 changed files with 384 additions and 3 deletions

View File

@ -12,7 +12,7 @@ OBJ_TYPE_CHOICES = (
('site', 'Sites'),
('rack', 'Racks'),
('rackgroup', 'Rack Groups'),
('devicetype', 'Device types'),
('devicetype', 'Device Types'),
('device', 'Devices'),
('virtualchassis', 'Virtual Chassis'),
('cable', 'Cables'),
@ -22,7 +22,7 @@ OBJ_TYPE_CHOICES = (
('vrf', 'VRFs'),
('aggregate', 'Aggregates'),
('prefix', 'Prefixes'),
('ipaddress', 'IP addresses'),
('ipaddress', 'IP Addresses'),
('vlan', 'VLANs'),
)),
('Secrets', (
@ -33,10 +33,21 @@ OBJ_TYPE_CHOICES = (
)),
('Virtualization', (
('cluster', 'Clusters'),
('virtualmachine', 'Virtual machines'),
('virtualmachine', 'Virtual Machines'),
)),
)
def build_options():
options = [{"label": OBJ_TYPE_CHOICES[0][1], "items": []}]
for label, choices in OBJ_TYPE_CHOICES[1:]:
items = []
for value, choice_label in choices:
items.append({"label": choice_label, "value": value})
options.append({"label": label, "items": items })
return options
class SearchForm(BootstrapMixin, forms.Form):
q = forms.CharField(
@ -45,3 +56,4 @@ class SearchForm(BootstrapMixin, forms.Form):
obj_type = forms.ChoiceField(
choices=OBJ_TYPE_CHOICES, required=False, label='Type'
)
options = build_options()

View File

@ -0,0 +1,36 @@
<div id="sidenav-accordion" class="accordion accordion-flush nav-item">
{% for menu in nav_items %}
<div class="accordion-item">
<a
href="#"
role="button"
aria-expanded="true"
data-bs-toggle="collapse"
data-bs-target="#{{ menu.label|lower }}"
class="d-flex justify-content-between align-items-center accordion-button nav-link collapsed"
><span class="fw-bold sidebar-nav-link">{{ menu.label }}</span></a
>
<div
id="{{ menu.label|lower }}"
class="accordion-collapse collapse"
data-bs-parent="#sidenav-accordion"
>
<div class="multi-level accordion-body px-0">
{% for group in menu.groups %}
<div class="flex-column nav px-2">
{% if menu.groups|length > 1 %}
<h6 class="accordion-item-title">{{ group.label }}</h6>
{% endif %} {% for item in group.items %}
<div class="nav-item">
<a class="nav-link" href="{% url item.url %}">{{ item.label }}</a>
</div>
{% endfor %}
</div>
{% if forloop.counter != menu.groups|length %}
<hr class="dropdown-divider my-3" />
{% endif %} {% endfor %}
</div>
</div>
</div>
{% endfor %}
</div>

View File

@ -0,0 +1,52 @@
<form class="input-group w-100" action="{% url 'search' %}" method="get">
<input
name="q"
id="id_q"
type="text"
aria-label="Search"
placeholder="Search"
class="form-control"
value="{{ request.GET.q }}"
aria-describedby="search-button"
/>
<input id="search-obj-type" name="obj_type" hidden type="text" />
<span class="input-group-text" id="selected-value">All Objects</span>
<button
type="button"
aria-expanded="false"
data-bs-toggle="dropdown"
class="btn btn-outline-secondary dropdown-toggle"
>
<i class="bi-filter"></i>
</button>
<ul id="object-type-selector" class="dropdown-menu dropdown-menu-end">
{% for option in options %} {% if option.items|length == 0 %}
<li>
<button
class="dropdown-item"
type="button"
data-search-value="{{ option.value }}"
>
{{ option.label }}
</button>
</li>
{% else %}
<li><h6 class="dropdown-header">{{ option.label }}</h6></li>
{% endif %} {% for item in option.items %}
<li>
<button
class="dropdown-item"
type="button"
data-search-value="{{ item.value }}"
>
{{ item.label }}
</button>
</li>
{% endfor %} {% if forloop.counter != options|length %}
<li><hr class="dropdown-divider" /></li>
{% endif %} {% endfor %}
</ul>
<button class="btn btn-primary" type="submit" id="search-button">
<i class="bi bi-search"></i>
</button>
</form>

View File

@ -0,0 +1,21 @@
from django import template
register = template.Library()
TERMS_DANGER = ("delete", "deleted", "remove", "removed")
TERMS_WARNING = ("changed", "updated", "change", "update")
TERMS_SUCCESS = ("created", "added", "create", "add")
@register.simple_tag
def get_status(text: str) -> str:
lower = text.lower()
if lower in TERMS_DANGER:
return "danger"
elif lower in TERMS_WARNING:
return "warning"
elif lower in TERMS_SUCCESS:
return "success"
else:
return "info"

View File

@ -0,0 +1,42 @@
from pathlib import Path
from typing import Dict, List
from django import template
from django.template import Context
from django.contrib.auth.context_processors import PermWrapper
import yaml
register = template.Library()
NAV_GROUPS = Path.cwd() / "utilities" / "templatetags" / "nav.yaml"
def import_groups() -> Dict:
with NAV_GROUPS.open("r") as f:
menus = yaml.safe_load(f.read())
return menus
def process_nav_group(nav_group: Dict, perms: PermWrapper) -> Dict:
"""Enable a menu item if view permissions exist for the user."""
for group in nav_group["groups"]:
for item in group["items"]:
# Parse the URL template tag to a permission string.
app, scope = item["url"].split(":")
view_perm = f"{app}.view_{scope}"
if view_perm in perms:
# If the view permission for each item exists, toggle
# the `disabled` field, which will be used in the UI.
item["disabled"] = False
return nav_group
@register.inclusion_tag("navigation/nav_items.html", takes_context=True)
def nav(context: Context) -> Dict:
"""Provide navigation items to template."""
perms: PermWrapper = context["perms"]
nav_menus = import_groups()
groups = [process_nav_group(g, perms) for g in nav_menus["menus"]]
return {"nav_items": groups, "request": context["request"]}

View File

@ -0,0 +1,205 @@
menus:
- label: Organization
groups:
- label: Sites
items:
- label: Sites
url: 'dcim:site_list'
disabled: true
- label: Regions
url: 'dcim:region_list'
disabled: true
- label: Racks
items:
- label: Racks
url: 'dcim:rack_list'
disabled: true
- label: Rack Groups
url: 'dcim:rackgroup_list'
disabled: true
- label: Rack Roles
url: 'dcim:rackrole_list'
disabled: true
- label: Elevations
url: 'dcim:rack_elevation_list'
disabled: true
- label: Tenancy
items:
- label: Tenants
url: 'tenancy:tenant_list'
disabled: true
- label: Tenant Groups
url: 'tenancy:tenantgroup_list'
disabled: true
- label: Tags
items:
- label: Tags
url: 'extras:tag_list'
disabled: true
- label: Devices
groups:
- items:
- disabled: true
label: Devices
url: dcim:device_list
- disabled: true
label: Device Roles
url: dcim:devicerole_list
- disabled: true
label: Platforms
url: dcim:platform_list
- disabled: true
label: Virtual Chassis
url: dcim:virtualchassis_list
label: Devices
- items:
- disabled: true
label: Device Types
url: dcim:devicetype_list
- disabled: true
label: Manufacturers
url: dcim:manufacturer_list
label: Device Types
- items:
- disabled: true
label: Cables
url: dcim:cable_list
- disabled: true
label: Console Connections
url: dcim:console_connections_list
- disabled: true
label: Interface Connections
url: dcim:interface_connections_list
- disabled: true
label: Power Connections
url: dcim:power_connections_list
label: Connections
- items:
- disabled: true
label: Interfaces
url: dcim:interface_list
- disabled: true
label: Front Ports
url: dcim:frontport_list
- disabled: true
label: Rear Ports
url: dcim:rearport_list
- disabled: true
label: Console Ports
url: dcim:consoleport_list
- disabled: true
label: Console Server Ports
url: dcim:consoleserverport_list
- disabled: true
label: Power Ports
url: dcim:powerport_list
- disabled: true
label: Power Outlets
url: dcim:poweroutlet_list
- disabled: true
label: Device Bays
url: dcim:devicebay_list
- disabled: true
label: Inventory Items
url: dcim:inventoryitem_list
label: Device Components
- label: IPAM
groups:
- label: IP Addresses
items:
- label: IP Addresses
url: 'ipam:ipaddress_list'
disabled: true
- label: Prefixes
items:
- label: Prefixes
url: 'ipam:prefix_list'
disabled: true
- label: Prefix & VLAN Roles
url: 'ipam:role_list'
disabled: true
- label: Aggregates
items:
- label: Aggregates
url: 'ipam:aggregate_list'
disabled: true
- label: RIRs
url: 'ipam:rir_list'
disabled: true
- label: VRFs
items:
- label: VRFs
url: 'ipam:vrf_list'
disabled: true
- label: Route Targets
url: 'ipam:routetarget_list'
disabled: true
- label: VLANs
items:
- label: VLANs
url: 'ipam:vlan_list'
disabled: true
- label: VLAN Groups
url: 'ipam:vlangroup_list'
disabled: true
- label: Services
items:
- label: Services
url: 'ipam:service_list'
disabled: true
- label: Virtualization
groups:
- label: Virtual Machines
items:
- label: Virtual Machines
url: 'virtualization:virtualmachine_list'
disabled: true
- label: Interfaces
url: 'virtualization:vminterface_list'
disabled: true
- label: Clusters
items:
- label: Clusters
url: 'virtualization:cluster_list'
disabled: true
- label: Cluster Types
url: 'virtualization:clustertype_list'
disabled: true
- label: Cluster Groups
url: 'virtualization:clustergroup_list'
disabled: true
- label: Circuits
groups:
- label: Circuits
items:
- label: Circuits
url: 'circuits:circuit_list'
disabled: true
- label: Circuit Types
url: 'circuits:circuittype_list'
disabled: true
- label: Providers
items:
- label: Providers
url: 'circuits:provider_list'
disabled: true
- label: Power
groups:
- label: Power
items:
- label: Power Feeds
url: 'dcim:powerfeed_list'
disabled: true
- label: Power Panels
url: 'dcim:powerpanel_list'
disabled: true
- label: Secrets
groups:
- label: Secrets
items:
- label: Secrets
url: 'secrets:secret_list'
disabled: true
- label: Secret Roles
url: 'secrets:secretrole_list'
disabled: true

View File

@ -0,0 +1,13 @@
from typing import Dict
from netbox.forms import SearchForm
from django import template
register = template.Library()
search_form = SearchForm()
@register.inclusion_tag("search/searchbar.html")
def search_options() -> Dict:
"""Provide search options to template."""
return {"options": search_form.options}