diff --git a/netbox/netbox/forms.py b/netbox/netbox/forms.py index 36198a384..da58e0c4f 100644 --- a/netbox/netbox/forms.py +++ b/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() diff --git a/netbox/utilities/templates/navigation/nav_items.html b/netbox/utilities/templates/navigation/nav_items.html new file mode 100644 index 000000000..ef9ccb1aa --- /dev/null +++ b/netbox/utilities/templates/navigation/nav_items.html @@ -0,0 +1,36 @@ + diff --git a/netbox/utilities/templates/search/searchbar.html b/netbox/utilities/templates/search/searchbar.html new file mode 100644 index 000000000..47ae17092 --- /dev/null +++ b/netbox/utilities/templates/search/searchbar.html @@ -0,0 +1,52 @@ +
+ + + All Objects + + + +
diff --git a/netbox/utilities/templatetags/get_status.py b/netbox/utilities/templatetags/get_status.py new file mode 100644 index 000000000..fde677053 --- /dev/null +++ b/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" diff --git a/netbox/utilities/templatetags/nav.py b/netbox/utilities/templatetags/nav.py new file mode 100644 index 000000000..bc995955a --- /dev/null +++ b/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"]} diff --git a/netbox/utilities/templatetags/nav.yaml b/netbox/utilities/templatetags/nav.yaml new file mode 100644 index 000000000..3f3cd8d3c --- /dev/null +++ b/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 diff --git a/netbox/utilities/templatetags/search_options.py b/netbox/utilities/templatetags/search_options.py new file mode 100644 index 000000000..aad533e7e --- /dev/null +++ b/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}