Ver Fonte

implement layout changes

checktheroads há 5 anos atrás
pai
commit
1d9e55ca6e

+ 15 - 3
netbox/netbox/forms.py

@@ -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()

+ 36 - 0
netbox/utilities/templates/navigation/nav_items.html

@@ -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>

+ 52 - 0
netbox/utilities/templates/search/searchbar.html

@@ -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>

+ 21 - 0
netbox/utilities/templatetags/get_status.py

@@ -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"

+ 42 - 0
netbox/utilities/templatetags/nav.py

@@ -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"]}

+ 205 - 0
netbox/utilities/templatetags/nav.yaml

@@ -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

+ 13 - 0
netbox/utilities/templatetags/search_options.py

@@ -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}