Compare commits

...
7 Commits
Author SHA1 Message Date
mattieserver 9b4dd77943 update version 2021-05-01 19:30:18 +02:00
mattieserver 91a690f1c8 add filter by locations (#63)
* frontend for locations

* locations filter backend
2021-05-01 19:22:28 +02:00
mattieserver 5f498f9ce2 Hide unconnected (#61)
* #57 hide unconnected devices
2021-05-01 18:34:50 +02:00
mattieserver 195ac47542 added docs to setup dev (#60) 2021-05-01 17:05:32 +02:00
julianze a25be917ee Update __init__.py (#55)
fix typo toplogoy
2021-03-28 11:40:03 +02:00
mattieserver 079361b190 Update README.md 2021-02-17 11:02:58 +01:00
mattieserverandmattieserver a314d2b307 netbox v2.10 (#52)
* small changes

* removed print

* fix coords

* fix saving coords

* update readme

* fixed icons

* bump version

Co-authored-by: mattieserver <mattijs@DESKTOP-618OSU1.localdomain>
2021-02-11 19:22:41 +01:00
15 changed files with 639 additions and 222 deletions
+10 -1
View File
@@ -1,5 +1,7 @@
# Netbox Topology Views Plugin # Netbox Topology Views Plugin
![Version](https://img.shields.io/pypi/v/netbox-topology-views) ![Downloads](https://img.shields.io/pypi/dm/netbox-topology-views)
Create topology views/maps from your devices in netbox. Create topology views/maps from your devices in netbox.
The connections are based on the cables you created in netbox. The connections are based on the cables you created in netbox.
Support to filter on name, site, tag and device role. Support to filter on name, site, tag and device role.
@@ -29,9 +31,16 @@ PLUGINS = ["netbox_topology_views"]
Then run `python3 manage.py collectstatic --no-input` Then run `python3 manage.py collectstatic --no-input`
### Versions
| netbox version | netbox-topology-views version |
| ------------- |-------------|
| >= 2.10.0 | >= v0.5.0 |
| < 2.10.0 | =< v0.4.10 |
### Custom field: coordinates ### Custom field: coordinates
There is also support for custom fiels. There is also support for custom fields.
If you create a custom field "coordinates" for "dcim > device" with type "text" and name "coordinates" you will see the same layout every time. If you create a custom field "coordinates" for "dcim > device" with type "text" and name "coordinates" you will see the same layout every time.
+22
View File
@@ -0,0 +1,22 @@
# Setup Dev
+ install docker
+ install docker compose
+ install npm
+ clone netbox repo
+ clone netbox_topology_views repo
+ create venv: `/usr/bin/python3 -m venv venv`
+ activate venv: `source venv/bin/activate`
+ install deps: `pip3 install -r requirements.txt`
+ install build tools: `python3 -m pip install --upgrade build setuptools wheel`
# Build
+ build the package: `python3 setup.py develop`
+ build the resources `npm run resources`
# Test
+ copy configuration.py from dev_setup to the netbox/netbox/ folder
+ run in the netbox repo: `python3 netbox/manage.py migrate`
+ (first time only) run in the netbox repo: `python3 netbox/manage.py createsuperuser`
+ run in the netbox repo: `python3 netbox/manage.py runserver`
+ browse to http://127.0.0.1:8000
+40
View File
@@ -0,0 +1,40 @@
###################################################################
# This file serves as a base configuration for testing purposes #
# only. It is not intended for production use. #
###################################################################
ALLOWED_HOSTS = ['*']
DATABASE = {
'NAME': 'netbox',
'USER': 'netbox',
'PASSWORD': 'J5brHrAXFLQSif0K',
'HOST': 'localhost',
'PORT': '',
'CONN_MAX_AGE': 300,
}
DEBUG = True
PLUGINS = [
'netbox_topology_views',
]
REDIS = {
'tasks': {
'HOST': 'localhost',
'PORT': 6379,
'PASSWORD': 't4Ph722qJ5QHeQ1qfu36',
'DATABASE': 0,
'SSL': False,
},
'caching': {
'HOST': 'localhost',
'PORT': 6378,
'PASSWORD': 'H733Kdjndks81',
'DATABASE': 1,
'SSL': False,
}
}
SECRET_KEY = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
+41
View File
@@ -0,0 +1,41 @@
version: '3.4'
services:
postgres:
image: postgres:12-alpine
environment:
POSTGRES_PASSWORD: J5brHrAXFLQSif0K #just for local dev
POSTGRES_DB: netbox
POSTGRES_USER: netbox
ports:
- "5432:5432"
volumes:
- netbox-postgres-data:/var/lib/postgresql/data
redis:
image: redis:6-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --appendonly yes --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
environment:
REDIS_PASSWORD: t4Ph722qJ5QHeQ1qfu36 #just for local dev
volumes:
- netbox-redis-data:/data
ports:
- "6379:6379"
redis-cache:
image: redis:6-alpine
command:
- sh
- -c # this is to evaluate the $REDIS_PASSWORD from the env
- redis-server --requirepass $$REDIS_PASSWORD ## $$ because of docker-compose
environment:
REDIS_PASSWORD: H733Kdjndks81 #just for local dev
ports:
- "6378:6379"
volumes:
netbox-postgres-data:
driver: local
netbox-redis-data:
driver: local
+2 -2
View File
@@ -3,8 +3,8 @@ from extras.plugins import PluginConfig
class TopologyViewsConfig(PluginConfig): class TopologyViewsConfig(PluginConfig):
name = 'netbox_topology_views' name = 'netbox_topology_views'
verbose_name = 'Topology views' verbose_name = 'Topology views'
description = 'An plugin to render toplogoy maps' description = 'An plugin to render topology maps'
version = '0.4.10' version = '0.5.3'
author = 'Mattijs Vanhaverbeke' author = 'Mattijs Vanhaverbeke'
author_email = 'author@example.com' author_email = 'author@example.com'
base_url = 'topology-views' base_url = 'topology-views'
+1
View File
@@ -0,0 +1 @@
"""REST API"""
+9 -7
View File
@@ -1,11 +1,13 @@
from rest_framework import routers from netbox.api import OrderedDefaultRouter
from . import views
from .views import PreSelectDeviceRolesViewSet, SearchViewSet, SaveCoordsViewSet, PreSelectTagsViewSet router = OrderedDefaultRouter()
router.APIRootView = views.TopologyViewsRootView
router = routers.DefaultRouter()
router.register('preselectdeviceroles', PreSelectDeviceRolesViewSet) router.register('preselectdeviceroles', views.PreSelectDeviceRolesViewSet)
router.register('preselecttags', PreSelectTagsViewSet) router.register('preselecttags', views.PreSelectTagsViewSet)
router.register('search', SearchViewSet, basename='search') router.register('search', views.SearchViewSet, basename='search')
router.register('save-coords', SaveCoordsViewSet, basename='save_coords') router.register('save-coords', views.SaveCoordsViewSet, basename='save_coords')
urlpatterns = router.urls urlpatterns = router.urls
+143 -131
View File
@@ -2,15 +2,15 @@ from rest_framework.viewsets import ModelViewSet, ViewSet, ReadOnlyModelViewSet,
from rest_framework.decorators import action from rest_framework.decorators import action
from rest_framework.response import Response from rest_framework.response import Response
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from rest_framework.routers import APIRootView
from .serializers import PreDeviceRoleSerializer, TopologyDummySerializer, PreTagSerializer from .serializers import PreDeviceRoleSerializer, TopologyDummySerializer, PreTagSerializer
from django.conf import settings from django.conf import settings
from utilities.api import IsAuthenticatedOrLoginNotRequired
from dcim.models import DeviceRole, Device, Cable from dcim.models import DeviceRole, Device, Cable
from circuits.models import Circuit from circuits.models import Circuit
from extras.models import Tag, CustomField, CustomFieldValue from extras.models import Tag
ignore_cable_type_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"] ignore_cable_type_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["ignore_cable_type"]
ignore_cable_type = ignore_cable_type_raw.split(",") ignore_cable_type = ignore_cable_type_raw.split(",")
@@ -21,6 +21,9 @@ preselected_device_roles = preselected_device_roles_raw.split(",")
preselected_tags_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_tags"] preselected_tags_raw = settings.PLUGINS_CONFIG["netbox_topology_views"]["preselected_tags"]
preselected_tags = preselected_tags_raw.split(",") preselected_tags = preselected_tags_raw.split(",")
class TopologyViewsRootView(APIRootView):
def get_view_name(self):
return 'TopologyViews'
class PreSelectDeviceRolesViewSet(ReadOnlyModelViewSet): class PreSelectDeviceRolesViewSet(ReadOnlyModelViewSet):
queryset = DeviceRole.objects.filter(name__in=preselected_device_roles) queryset = DeviceRole.objects.filter(name__in=preselected_device_roles)
@@ -38,14 +41,6 @@ class SaveCoordsViewSet(ReadOnlyModelViewSet):
def save_coords(self, request): def save_coords(self, request):
results = {} results = {}
if settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"]: if settings.PLUGINS_CONFIG["netbox_topology_views"]["allow_coordinates_saving"]:
try:
cfCoords = CustomField.objects.get(name='coordinates')
except CustomField.DoesNotExist:
results["status"] = "coords custom field not created"
return Response(status=500)
obj_type = ContentType.objects.get_for_model(Device)
device_id = None device_id = None
x_coord = None x_coord = None
y_coord = None y_coord = None
@@ -60,30 +55,30 @@ class SaveCoordsViewSet(ReadOnlyModelViewSet):
y_coord = request.data["y"] y_coord = request.data["y"]
actual_device= Device.objects.get(id=device_id) actual_device= Device.objects.get(id=device_id)
try:
cfvCoords = CustomFieldValue.objects.get(obj_type=obj_type, obj_id=actual_device.pk, field__name='coordinates') if "coordinates" in actual_device.custom_field_data:
cfvCoords.value = "%s;%s" % (x_coord,y_coord) actual_device.custom_field_data["coordinates"] = "%s;%s" % (x_coord,y_coord)
cfvCoords.save() actual_device.save()
results["status"] = "coords set" results["status"] = "saved coords"
except CustomFieldValue.DoesNotExist: else:
cfvCoords = CustomFieldValue(field=cfCoords, obj_type=obj_type, obj_id=actual_device.id) try:
cfvCoords.value = "%s;%s" % (x_coord,y_coord) actual_device.custom_field_data["coordinates"] = "%s;%s" % (x_coord,y_coord)
cfvCoords.save() actual_device.save()
results["status"] = "coords set for first time" results["status"] = "saved coords"
except :
results["status"] = "coords custom field not created"
return Response(status=500)
return Response(results) return Response(results)
else: else:
results["status"] = "not allowed to save coords" results["status"] = "not allowed to save coords"
return Response(results, status=500) return Response(results, status=500)
class SearchViewSet(ReadOnlyModelViewSet): class SearchViewSet(ReadOnlyModelViewSet):
#_ignore_model_permissions = True
#permission_classes = [IsAuthenticatedOrLoginNotRequired]
queryset = Device.objects.all() queryset = Device.objects.all()
serializer_class = TopologyDummySerializer serializer_class = TopologyDummySerializer
def _filter(self, site, role, name, tags, region): def _filter(self, site, role, name, tags, region, location):
filter_devices = Device.objects.all() filter_devices = Device.objects.all()
if name is not None: if name is not None:
filter_devices = filter_devices.filter(name__contains=name) filter_devices = filter_devices.filter(name__contains=name)
@@ -95,6 +90,8 @@ class SearchViewSet(ReadOnlyModelViewSet):
filter_devices = filter_devices.filter(tags__id__in=tags) filter_devices = filter_devices.filter(tags__id__in=tags)
if region is not None: if region is not None:
filter_devices = filter_devices.filter(site__region__id__in=region) filter_devices = filter_devices.filter(site__region__id__in=region)
if location is not None:
filter_devices = filter_devices.filter(location__id__in=location)
return filter_devices return filter_devices
@@ -120,7 +117,15 @@ class SearchViewSet(ReadOnlyModelViewSet):
if regions == []: if regions == []:
regions = None regions = None
devices = self._filter(sites, devicerole, name, tags, regions) locations = request.query_params.getlist('locations[]', None)
if locations == []:
locations = None
hide_unconnected = request.query_params.get('hide_unconnected', None)
if hide_unconnected == "":
hide_unconnected = None
devices = self._filter(sites, devicerole, name, tags, regions, locations)
nodes = [] nodes = []
edges = [] edges = []
@@ -129,41 +134,21 @@ class SearchViewSet(ReadOnlyModelViewSet):
circuit_ids = [] circuit_ids = []
for device in devices: for device in devices:
cables = device.get_cables() cables = device.get_cables()
for cable in cables: if cables.exists():
if cable.termination_a_type.name != "circuit termination" and cable.termination_b_type.name != "circuit termination": device_has_connections = True
if cable.id not in cable_ids: for cable in cables:
if cable.termination_a_type.name not in ignore_cable_type and cable.termination_b_type.name not in ignore_cable_type: if cable.termination_a_type.name != "circuit termination" and cable.termination_b_type.name != "circuit termination":
cable_ids.append(cable.id) if cable.id not in cable_ids:
edge_ids += 1 if cable.termination_a_type.name not in ignore_cable_type and cable.termination_b_type.name not in ignore_cable_type:
cable_ids.append(cable.id)
cable_a_dev_name = cable.termination_a.device.name
if cable_a_dev_name is None:
cable_a_dev_name = "device A name unknown"
cable_a_name = cable.termination_a.name
if cable_a_name is None:
cable_a_name = "cable A name unknown"
cable_b_dev_name = cable.termination_b.device.name
if cable_b_dev_name is None:
cable_b_dev_name = "device B name unknown"
cable_b_name = cable.termination_b.name
if cable_b_name is None:
cable_b_name = "cable B name unknown"
edge = {}
edge["id"] = edge_ids
edge["from"] = cable.termination_a.device.id
edge["to"] = cable.termination_b.device.id
edge["title"] = "Cable between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
if cable.color != "":
edge["color"] = "#" + cable.color
edges.append(edge)
else:
if cable.termination_a_type.name == "circuit termination":
if settings.PLUGINS_CONFIG["netbox_topology_views"]["enable_circuit_terminations"]:
if cable.termination_a.circuit.id not in circuit_ids:
circuit_ids.append(cable.termination_a.circuit.id)
edge_ids += 1 edge_ids += 1
cable_a_dev_name = cable.termination_a.device.name
if cable_a_dev_name is None:
cable_a_dev_name = "device A name unknown"
cable_a_name = cable.termination_a.name
if cable_a_name is None:
cable_a_name = "cable A name unknown"
cable_b_dev_name = cable.termination_b.device.name cable_b_dev_name = cable.termination_b.device.name
if cable_b_dev_name is None: if cable_b_dev_name is None:
cable_b_dev_name = "device B name unknown" cable_b_dev_name = "device B name unknown"
@@ -173,89 +158,116 @@ class SearchViewSet(ReadOnlyModelViewSet):
edge = {} edge = {}
edge["id"] = edge_ids edge["id"] = edge_ids
edge["from"] = cable.termination_a.device.id
edge["to"] = cable.termination_b.device.id edge["to"] = cable.termination_b.device.id
edge["dashes"] = True edge["title"] = "Cable between <br> " + cable_a_dev_name + " [" + cable_a_name + "]<br>" + cable_b_dev_name + " [" + cable_b_name + "]"
title = "" if cable.color != "":
edge["color"] = "#" + cable.color
edges.append(edge)
else:
if cable.termination_a_type.name == "circuit termination":
if settings.PLUGINS_CONFIG["netbox_topology_views"]["enable_circuit_terminations"]:
if cable.termination_a.circuit.id not in circuit_ids:
circuit_ids.append(cable.termination_a.circuit.id)
edge_ids += 1
title += "Circuit provider: " + cable.termination_a.circuit.provider.name + "<br>" cable_b_dev_name = cable.termination_b.device.name
title += "Termination between <br>" if cable_b_dev_name is None:
title += cable_b_dev_name + " [" + cable_b_name + "]<br>" cable_b_dev_name = "device B name unknown"
# To Many if's cable_b_name = cable.termination_b.name
if cable.termination_a.circuit.termination_a is not None: if cable_b_name is None:
if cable.termination_a.circuit.termination_a.cable is not None: cable_b_name = "cable B name unknown"
if cable.termination_a.circuit.termination_a.cable.id != cable.id:
if cable.termination_a.circuit.termination_a.cable.termination_b is not None:
if cable.termination_a.circuit.termination_a.cable.termination_b.device is not None:
edge["from"] = cable.termination_a.circuit.termination_a.cable.termination_b.device.id
cable_a_dev_name = cable.termination_a.circuit.termination_a.cable.termination_b.device.name edge = {}
if cable_a_dev_name is None: edge["id"] = edge_ids
cable_a_dev_name = "device B name unknown" edge["to"] = cable.termination_b.device.id
cable_b_name = cable.termination_a.circuit.termination_a.cable.termination_b.name edge["dashes"] = True
if cable_a_name is None: title = ""
cable_a_name = "cable B name unknown"
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
edge["title"] = title
edges.append(edge)
# To Many if's
if cable.termination_a.circuit.termination_z is not None:
if cable.termination_a.circuit.termination_z.cable is not None:
if cable.termination_a.circuit.termination_z.cable.id != cable.id:
if cable.termination_a.circuit.termination_z.cable.termination_b is not None:
if cable.termination_a.circuit.termination_z.cable.termination_b.device is not None:
edge["from"] = cable.termination_a.circuit.termination_z.cable.termination_b.device.id
cable_a_dev_name = cable.termination_a.circuit.termination_z.cable.termination_b.device.name title += "Circuit provider: " + cable.termination_a.circuit.provider.name + "<br>"
if cable_a_dev_name is None: title += "Termination between <br>"
cable_a_dev_name = "device B name unknown" title += cable_b_dev_name + " [" + cable_b_name + "]<br>"
cable_a_name = cable.termination_a.circuit.termination_z.cable.termination_b.name # To Many if's
if cable_a_name is None: if cable.termination_a.circuit.termination_a is not None:
cable_a_name = "cable B name unknown" if cable.termination_a.circuit.termination_a.cable is not None:
title += cable_a_dev_name + " [" + cable_a_name + "]<br>" if cable.termination_a.circuit.termination_a.cable.id != cable.id:
edge["title"] = title if cable.termination_a.circuit.termination_a.cable.termination_b is not None:
edges.append(edge) if cable.termination_a.circuit.termination_a.cable.termination_b.device is not None:
dev_name = device.name edge["from"] = cable.termination_a.circuit.termination_a.cable.termination_b.device.id
if dev_name is None:
dev_name = "device name unknown"
node_content = "" cable_a_dev_name = cable.termination_a.circuit.termination_a.cable.termination_b.device.name
if cable_a_dev_name is None:
cable_a_dev_name = "device B name unknown"
cable_b_name = cable.termination_a.circuit.termination_a.cable.termination_b.name
if cable_a_name is None:
cable_a_name = "cable B name unknown"
title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
edge["title"] = title
edges.append(edge)
# To Many if's
if cable.termination_a.circuit.termination_z is not None:
if cable.termination_a.circuit.termination_z.cable is not None:
if cable.termination_a.circuit.termination_z.cable.id != cable.id:
if cable.termination_a.circuit.termination_z.cable.termination_b is not None:
if cable.termination_a.circuit.termination_z.cable.termination_b.device is not None:
edge["from"] = cable.termination_a.circuit.termination_z.cable.termination_b.device.id
if device.device_type.display_name is not None: cable_a_dev_name = cable.termination_a.circuit.termination_z.cable.termination_b.device.name
node_content += "<tr><th>Type: </th><td>" + device.device_type.display_name + "</td></tr>" if cable_a_dev_name is None:
if device.device_role.name is not None: cable_a_dev_name = "device B name unknown"
node_content += "<tr><th>Role: </th><td>" + device.device_role.name + "</td></tr>" cable_a_name = cable.termination_a.circuit.termination_z.cable.termination_b.name
if device.serial != "": if cable_a_name is None:
node_content += "<tr><th>Serial: </th><td>" + device.serial + "</td></tr>" cable_a_name = "cable B name unknown"
if device.primary_ip is not None: title += cable_a_dev_name + " [" + cable_a_name + "]<br>"
node_content += "<tr><th>IP Address: </th><td>" + str(device.primary_ip.address) + "</td></tr>" edge["title"] = title
edges.append(edge)
dev_title = "<table> %s </table>" % (node_content)
node = {}
node["id"] = device.id
node["name"] = dev_name
node["label"] = dev_name
node["title"] = dev_title
node["shape"] = 'image'
if device.device_role.slug in settings.PLUGINS_CONFIG["netbox_topology_views"]["device_img"]:
node["image"] = '../../static/netbox_topology_views/img/' + device.device_role.slug + ".png"
else: else:
node["image"] = "../../static/netbox_topology_views/img/role-unknown.png" device_has_connections = False
if device.device_role.color != "": if hide_unconnected == 'false' or (hide_unconnected == 'true' and device_has_connections is True):
node["color.border"] = "#" + device.device_role.color dev_name = device.name
if dev_name is None:
dev_name = "device name unknown"
for device_custom_field in device.custom_field_values.all(): node_content = ""
if device_custom_field.field.name == "coordinates":
cords = device_custom_field.serialized_value.split(";") if device.device_type.display_name is not None:
node["x"] = int(cords[0]) node_content += "<tr><th>Type: </th><td>" + device.device_type.display_name + "</td></tr>"
node["y"] = int(cords[1]) if device.device_role.name is not None:
node["physics"] = False node_content += "<tr><th>Role: </th><td>" + device.device_role.name + "</td></tr>"
if device.serial != "":
nodes.append(node) node_content += "<tr><th>Serial: </th><td>" + device.serial + "</td></tr>"
if device.primary_ip is not None:
node_content += "<tr><th>IP Address: </th><td>" + str(device.primary_ip.address) + "</td></tr>"
dev_title = "<table> %s </table>" % (node_content)
node = {}
node["id"] = device.id
node["name"] = dev_name
node["label"] = dev_name
node["title"] = dev_title
node["shape"] = 'image'
if device.device_role.slug in settings.PLUGINS_CONFIG["netbox_topology_views"]["device_img"]:
node["image"] = '../../static/netbox_topology_views/img/' + device.device_role.slug + ".png"
else:
node["image"] = "../../static/netbox_topology_views/img/role-unknown.png"
if device.device_role.color != "":
node["color.border"] = "#" + device.device_role.color
if "coordinates" in device.custom_field_data:
if device.custom_field_data["coordinates"] != "":
cords = device.custom_field_data["coordinates"].split(";")
node["x"] = int(cords[0])
node["y"] = int(cords[1])
node["physics"] = False
nodes.append(node)
results = {} results = {}
results["nodes"] = nodes results["nodes"] = nodes
results["edges"] = edges results["edges"] = edges
return Response(results) return Response(results)
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+66 -2
View File
@@ -33,6 +33,7 @@ var options = {
} }
}; };
var selected_regions = []; var selected_regions = [];
var selected_sites = [];
function iniPlotboxIndex() { function iniPlotboxIndex() {
document.addEventListener('DOMContentLoaded', function () { document.addEventListener('DOMContentLoaded', function () {
@@ -113,6 +114,25 @@ function startLoadSearchBar() {
} }
} }
}); });
$('#sites').on('select2:select', function (e) {
var data = e.params.data;
var index = selected_sites.indexOf(data.id.toString());
if (index == -1) {
selected_sites.push(data.id.toString());
}
});
$('#sites').on('select2:unselect', function (e) {
var data = e.params.data;
var index = selected_sites.indexOf(data.id.toString());
if (index > -1) {
selected_sites.splice(index, 1);
}
});
$('#sites').on('select2:clear', function (e) {
selected_sites = [];
});
$('#tags').select2({ $('#tags').select2({
allowClear: true, allowClear: true,
placeholder: "---------", placeholder: "---------",
@@ -178,7 +198,6 @@ function startLoadSearchBar() {
$('#regions').on('select2:unselect', function (e) { $('#regions').on('select2:unselect', function (e) {
var data = e.params.data; var data = e.params.data;
var index = selected_regions.indexOf(data.id.toString()); var index = selected_regions.indexOf(data.id.toString());
console.log(index);
if (index > -1) { if (index > -1) {
selected_regions.splice(index, 1); selected_regions.splice(index, 1);
} }
@@ -187,6 +206,47 @@ function startLoadSearchBar() {
selected_regions = []; selected_regions = [];
}); });
$('#locations').select2({
allowClear: true,
placeholder: "---------",
theme: "bootstrap",
multiple: true,
ajax: {
url: function (params) {
var base_url = "../../api/dcim/locations/?brief=true";
if (selected_sites.length == 0) {
return base_url;
}
else {
for (var i = 0; i < selected_sites.length; i++) {
var tmp = "&site_id=" + selected_sites[i];
base_url = base_url + tmp;
}
return base_url;
}
},
dataType: "json",
type: "GET",
data: function (params) {
var queryParameters = {
q: params.term
}
return queryParameters;
},
processResults: function (data) {
return {
results: $.map(data.results, function (item) {
return {
text: item.name,
id: item.id
}
})
};
}
}
});
var deviceRolesSelect = $('#device-roles'); var deviceRolesSelect = $('#device-roles');
$.ajax({ $.ajax({
@@ -232,6 +292,8 @@ function handleButtonPress() {
var value3 = $("#sites").val(); var value3 = $("#sites").val();
var value4 = $("#tags").val(); var value4 = $("#tags").val();
var value5 = $("#regions").val(); var value5 = $("#regions").val();
var value6 = $('#checkHideUnconnected').is(":checked");
var value7 = $("#locations").val();
$.ajax({ $.ajax({
type: "GET", type: "GET",
url: "../../api/plugins/topology-views/search/search/", url: "../../api/plugins/topology-views/search/search/",
@@ -240,7 +302,9 @@ function handleButtonPress() {
'devicerole[]': value2, 'devicerole[]': value2,
'sites[]': value3, 'sites[]': value3,
'tags[]': value4, 'tags[]': value4,
'regions[]': value5 'regions[]': value5,
'hide_unconnected': value6,
'locations[]': value7
}, },
headers: { "X-CSRFToken": csrftoken }, headers: { "X-CSRFToken": csrftoken },
contentType: "application/json; charset=utf-8", contentType: "application/json; charset=utf-8",
@@ -14,10 +14,10 @@
<strong>Network</strong> <span id="status"></span> <strong>Network</strong> <span id="status"></span>
<div class="buttons pull-right"> <div class="buttons pull-right">
<a id="btnDownloadImage" class="btn btn-xs btn-info"> <a id="btnDownloadImage" class="btn btn-xs btn-info">
<i class="fa fa-download"></i> <i class="mdi mdi-download"></i>
</a> </a>
<a id="btnFullView" class="btn btn-xs btn-info disabled" target="_blank"> <a id="btnFullView" class="btn btn-xs btn-info disabled" target="_blank">
<i class="fa fa-share"></i> <i class="mdi mdi-share"></i>
</a> </a>
</div> </div>
</div> </div>
@@ -41,18 +41,28 @@
<div class="form-group"> <div class="form-group">
<label for="device-roles">Device roles</label> <label for="device-roles">Device roles</label>
<select class="form-control" multiple="multiple" id="device-roles"></select> <select class="form-control" multiple="multiple" id="device-roles"></select>
</div>
<div class="form-group">
<label for="regions">Regions</label>
<select class="form-control" multiple="multiple" id="regions"></select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="sites">Sites</label> <label for="sites">Sites</label>
<select class="form-control" multiple="multiple" id="sites"></select> <select class="form-control" multiple="multiple" id="sites"></select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="locations">Locations</label>
<select class="form-control" multiple="multiple" id="locations"></select>
</div>
<div class="form-group">
<label for="tags">Tags</label> <label for="tags">Tags</label>
<select class="form-control" multiple="multiple" id="tags"></select> <select class="form-control" multiple="multiple" id="tags"></select>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="regions">Regions</label> <div class="custom-control custom-checkbox">
<select class="form-control" multiple="multiple" id="regions"></select> <input type="checkbox" class="custom-control-input" id="checkHideUnconnected">
<label class="custom-control-label" for="checkHideUnconnected">Hide Unconnected</label>
</div>
</div> </div>
<hr class="mb-4"> <hr class="mb-4">
<button class="btn btn-primary btn-lg btn-block" type="submit" id="start-search">Search</button> <button class="btn btn-primary btn-lg btn-block" type="submit" id="start-search">Search</button>
+282 -64
View File
@@ -1,9 +1,24 @@
{ {
"name": "netbox_topology_views", "name": "netbox_topology_views",
"version": "0.4.8", "version": "0.5.3",
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@egjs/hammerjs": {
"version": "2.0.17",
"resolved": "https://registry.npmjs.org/@egjs/hammerjs/-/hammerjs-2.0.17.tgz",
"integrity": "sha512-XQsZgjm2EcVUiZQf11UBJQfmZeEmOW8DpI1gsFeln6w0ae0ii4dMQEQ0kjl6DspdWX1aGY1/loyXnP0JS06e/A==",
"dev": true,
"requires": {
"@types/hammerjs": "^2.0.36"
}
},
"@types/hammerjs": {
"version": "2.0.38",
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.38.tgz",
"integrity": "sha512-wuwDzWW1JWh3BZoRftBlKcctjNzR75QFY4/b4zAz7sH1EesA8HBJzke+bF5dxCATNdHHs3X1P5UWanbbUT6chw==",
"dev": true
},
"abbrev": { "abbrev": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@@ -11,9 +26,9 @@
"dev": true "dev": true
}, },
"ajv": { "ajv": {
"version": "6.12.0", "version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dev": true, "dev": true,
"requires": { "requires": {
"fast-deep-equal": "^3.1.1", "fast-deep-equal": "^3.1.1",
@@ -295,9 +310,9 @@
"dev": true "dev": true
}, },
"aws4": { "aws4": {
"version": "1.9.1", "version": "1.11.0",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
"integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug==", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
"dev": true "dev": true
}, },
"bach": { "bach": {
@@ -1503,6 +1518,12 @@
"safer-buffer": "^2.1.0" "safer-buffer": "^2.1.0"
} }
}, },
"emoji-regex": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
"integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
"dev": true
},
"end-of-stream": { "end-of-stream": {
"version": "1.4.4", "version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -1743,9 +1764,9 @@
} }
}, },
"fast-deep-equal": { "fast-deep-equal": {
"version": "3.1.1", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
"dev": true "dev": true
}, },
"fast-json-stable-stringify": { "fast-json-stable-stringify": {
@@ -2054,13 +2075,13 @@
} }
}, },
"globule": { "globule": {
"version": "1.3.1", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/globule/-/globule-1.3.1.tgz", "resolved": "https://registry.npmjs.org/globule/-/globule-1.3.2.tgz",
"integrity": "sha512-OVyWOHgw29yosRHCHo7NncwR1hW5ew0W/UrvtwvjefVJeQ26q4/8r8FmPsSF1hJ93IgWkyv16pCTz6WblMzm/g==", "integrity": "sha512-7IDTQTIu2xzXkT+6mlluidnWo+BypnbSoEVVQCGfzqnl5Ik8d3e1d4wycb8Rj9tWW+Z39uPWsdlquqiqPCd/pA==",
"dev": true, "dev": true,
"requires": { "requires": {
"glob": "~7.1.1", "glob": "~7.1.1",
"lodash": "~4.17.12", "lodash": "~4.17.10",
"minimatch": "~3.0.2" "minimatch": "~3.0.2"
} }
}, },
@@ -2154,13 +2175,13 @@
} }
}, },
"gulp-sass": { "gulp-sass": {
"version": "4.0.2", "version": "4.1.0",
"resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.0.2.tgz", "resolved": "https://registry.npmjs.org/gulp-sass/-/gulp-sass-4.1.0.tgz",
"integrity": "sha512-q8psj4+aDrblJMMtRxihNBdovfzGrXJp1l4JU0Sz4b/Mhsi2DPrKFYCGDwjIWRENs04ELVHxdOJQ7Vs98OFohg==", "integrity": "sha512-xIiwp9nkBLcJDpmYHbEHdoWZv+j+WtYaKD6Zil/67F3nrAaZtWYN5mDwerdo7EvcdBenSAj7Xb2hx2DqURLGdA==",
"dev": true, "dev": true,
"requires": { "requires": {
"chalk": "^2.3.0", "chalk": "^2.3.0",
"lodash.clonedeep": "^4.3.2", "lodash": "^4.17.11",
"node-sass": "^4.8.3", "node-sass": "^4.8.3",
"plugin-error": "^1.0.1", "plugin-error": "^1.0.1",
"replace-ext": "^1.0.0", "replace-ext": "^1.0.0",
@@ -2220,12 +2241,12 @@
"dev": true "dev": true
}, },
"har-validator": { "har-validator": {
"version": "5.1.3", "version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==", "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"dev": true, "dev": true,
"requires": { "requires": {
"ajv": "^6.5.5", "ajv": "^6.12.3",
"har-schema": "^2.0.0" "har-schema": "^2.0.0"
} }
}, },
@@ -2355,9 +2376,9 @@
"dev": true "dev": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
"dev": true "dev": true
}, },
"interpret": { "interpret": {
@@ -2600,9 +2621,9 @@
"dev": true "dev": true
}, },
"js-base64": { "js-base64": {
"version": "2.5.2", "version": "2.6.4",
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.2.tgz", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.6.4.tgz",
"integrity": "sha512-Vg8czh0Q7sFBSUMWWArX/miJeBWYBPpdU/3M/DKSaekLMqrqVPaedp+5mZhie/r0lgrcaYBfwXatEew6gwgiQQ==", "integrity": "sha512-pZe//GGmwJndub7ZghVHz7vjb2LgC1m8B07Au3eYqeqv9emhESByMXxaEgkUkEqJe87oBbSniGYoQNIBklc7IQ==",
"dev": true "dev": true
}, },
"jsbn": { "jsbn": {
@@ -2653,6 +2674,12 @@
"integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=", "integrity": "sha1-h/zPrv/AtozRnVX2cilD+SnqNeo=",
"dev": true "dev": true
}, },
"keycharm": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/keycharm/-/keycharm-0.3.1.tgz",
"integrity": "sha512-zn47Ti4FJT9zdF+YBBLWJsfKF/fYQHkrYlBeB5Ez5e2PjW7SoIxr43yehAne2HruulIoid4NKZZxO0dHBygCtQ==",
"dev": true
},
"kind-of": { "kind-of": {
"version": "6.0.3", "version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
@@ -2725,16 +2752,28 @@
"strip-bom": "^2.0.0" "strip-bom": "^2.0.0"
} }
}, },
"lodash": { "locate-path": {
"version": "4.17.19", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.19.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
"integrity": "sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==", "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
"dev": true "dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
},
"dependencies": {
"path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=",
"dev": true
}
}
}, },
"lodash.clonedeep": { "lodash": {
"version": "4.5.0", "version": "4.17.20",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
"dev": true "dev": true
}, },
"loud-rejection": { "loud-rejection": {
@@ -2877,18 +2916,18 @@
} }
}, },
"mime-db": { "mime-db": {
"version": "1.43.0", "version": "1.45.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.45.0.tgz",
"integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==", "integrity": "sha512-CkqLUxUk15hofLoLyljJSrukZi8mAtgd+yE5uO4tqRZsdsAJKv0O+rFMhVDRJgozy+yG6md5KwuXhD4ocIoP+w==",
"dev": true "dev": true
}, },
"mime-types": { "mime-types": {
"version": "2.1.26", "version": "2.1.28",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.28.tgz",
"integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", "integrity": "sha512-0TO2yJ5YHYr7M2zzT7gDU1tbwHxEUWBCLt0lscSNpcdAfFyJOVEpRYNS7EXVcTLNj/25QO8gulHC5JtTzSE2UQ==",
"dev": true, "dev": true,
"requires": { "requires": {
"mime-db": "1.43.0" "mime-db": "1.45.0"
} }
}, },
"minimatch": { "minimatch": {
@@ -2936,6 +2975,12 @@
"minimist": "^1.2.5" "minimist": "^1.2.5"
} }
}, },
"moment": {
"version": "2.29.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.29.1.tgz",
"integrity": "sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==",
"dev": true
},
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -3008,9 +3053,9 @@
} }
}, },
"node-sass": { "node-sass": {
"version": "4.13.1", "version": "4.14.1",
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.13.1.tgz", "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.14.1.tgz",
"integrity": "sha512-TTWFx+ZhyDx1Biiez2nB0L3YrCZ/8oHagaDalbuBSlqXgUPsdkUSzJsVxeDO9LtPB49+Fh3WQl3slABo6AotNw==", "integrity": "sha512-sjCuOlvGyCJS40R8BscF5vhVlQjNN069NtQ1gSxyK1u9iqvn6tf7O1R4GNowVZfiZUCRt5MmMs1xd+4V/7Yr0g==",
"dev": true, "dev": true,
"requires": { "requires": {
"async-foreach": "^0.1.3", "async-foreach": "^0.1.3",
@@ -3027,7 +3072,7 @@
"node-gyp": "^3.8.0", "node-gyp": "^3.8.0",
"npmlog": "^4.0.0", "npmlog": "^4.0.0",
"request": "^2.88.0", "request": "^2.88.0",
"sass-graph": "^2.2.4", "sass-graph": "2.2.5",
"stdout-stream": "^1.4.0", "stdout-stream": "^1.4.0",
"true-case-path": "^1.0.2" "true-case-path": "^1.0.2"
}, },
@@ -3276,6 +3321,30 @@
"os-tmpdir": "^1.0.0" "os-tmpdir": "^1.0.0"
} }
}, },
"p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true
},
"parse-filepath": { "parse-filepath": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz",
@@ -3636,6 +3705,14 @@
"tough-cookie": "~2.5.0", "tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0",
"uuid": "^3.3.2" "uuid": "^3.3.2"
},
"dependencies": {
"uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"dev": true
}
} }
}, },
"require-directory": { "require-directory": {
@@ -3721,15 +3798,138 @@
"dev": true "dev": true
}, },
"sass-graph": { "sass-graph": {
"version": "2.2.4", "version": "2.2.5",
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.4.tgz", "resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.2.5.tgz",
"integrity": "sha1-E/vWPNHK8JCLn9k0dq1DpR0eC0k=", "integrity": "sha512-VFWDAHOe6mRuT4mZRd4eKE+d8Uedrk6Xnh7Sh9b4NGufQLQjOrvf/MQoOdx+0s92L89FeyUUNfU597j/3uNpag==",
"dev": true, "dev": true,
"requires": { "requires": {
"glob": "^7.0.0", "glob": "^7.0.0",
"lodash": "^4.0.0", "lodash": "^4.0.0",
"scss-tokenizer": "^0.2.3", "scss-tokenizer": "^0.2.3",
"yargs": "^7.0.0" "yargs": "^13.3.2"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
"integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
"dev": true
},
"camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true
},
"cliui": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
"integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
"dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"find-up": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=",
"dev": true
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true
},
"string-width": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
"integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
"integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=",
"dev": true
},
"wrap-ansi": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
"integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"y18n": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz",
"integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==",
"dev": true
},
"yargs": {
"version": "13.3.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
"integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
"dev": true,
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.2"
}
},
"yargs-parser": {
"version": "13.1.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
"integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
} }
}, },
"scss-tokenizer": { "scss-tokenizer": {
@@ -4150,6 +4350,12 @@
"integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=",
"dev": true "dev": true
}, },
"timsort": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
"dev": true
},
"to-absolute-glob": { "to-absolute-glob": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz", "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-2.0.2.tgz",
@@ -4370,9 +4576,9 @@
"dev": true "dev": true
}, },
"uri-js": { "uri-js": {
"version": "4.2.2", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dev": true, "dev": true,
"requires": { "requires": {
"punycode": "^2.1.0" "punycode": "^2.1.0"
@@ -4397,9 +4603,9 @@
"dev": true "dev": true
}, },
"uuid": { "uuid": {
"version": "3.4.0", "version": "7.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", "integrity": "sha512-LNUrNsXdI/fUsypJbWM8Jt4DgQdFAZh41p9C7WE9Cn+CULOEkoG2lgQyH68v3wnIy5K3fN4jdSt270K6IFA3MQ==",
"dev": true "dev": true
}, },
"v8flags": { "v8flags": {
@@ -4501,10 +4707,22 @@
"source-map": "^0.5.1" "source-map": "^0.5.1"
} }
}, },
"vis-data": {
"version": "6.6.1",
"resolved": "https://registry.npmjs.org/vis-data/-/vis-data-6.6.1.tgz",
"integrity": "sha512-xmujDB2Dzf8T04rGFJ9OP4OA6zRVrz8R9hb0CVKryBrZRCljCga9JjSfgctA8S7wdZu7otDtUIwX4ZOgfV/57w==",
"dev": true
},
"vis-network": { "vis-network": {
"version": "7.10.0", "version": "7.10.2",
"resolved": "https://registry.npmjs.org/vis-network/-/vis-network-7.10.0.tgz", "resolved": "https://registry.npmjs.org/vis-network/-/vis-network-7.10.2.tgz",
"integrity": "sha512-SYQ3y+cGqcFpPfaQbpGBXsaQjjbQq5xjt5dVztCD6x5ETQHlAYaFiYiWnVo0qoVI9lspfwoCfp4wOhW+rvId6Q==", "integrity": "sha512-KDx2agbDnaiE0Bye4AcCRqTn5mxzDKhdUNpKkzSn0AOLBmdhNtPGjxAFluAmvFVyiSK5R6Q5KIWdLjeIMu/PAQ==",
"dev": true
},
"vis-util": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/vis-util/-/vis-util-4.3.4.tgz",
"integrity": "sha512-hJIZNrwf4ML7FYjs+m+zjJfaNvhjk3/1hbMdQZVnwwpOFJS/8dMG8rdbOHXcKoIEM6U5VOh3HNpaDXxGkOZGpw==",
"dev": true "dev": true
}, },
"which": { "which": {
@@ -4554,9 +4772,9 @@
"dev": true "dev": true
}, },
"y18n": { "y18n": {
"version": "3.2.1", "version": "3.2.2",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.2.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=", "integrity": "sha512-uGZHXkHnhF0XeeAPgnKfPv1bgKAYyVvmNL1xlKsPYZPaIHxGti2hHqvOCQv71XMsLxu1QjergkqogUnms5D3YQ==",
"dev": true "dev": true
}, },
"yallist": { "yallist": {
+6 -8
View File
@@ -1,28 +1,26 @@
{ {
"private": true, "private": true,
"name": "netbox_topology_views", "name": "netbox_topology_views",
"version": "0.4.10", "version": "0.5.3",
"scripts": { "scripts": {
"resources": "gulp build", "resources": "gulp build",
"resources_dev": "gulp build_dev" "resources_dev": "gulp build_dev"
}, },
"dependencies": {}, "dependencies": {},
"devDependencies": { "devDependencies": {
"@egjs/hammerjs": "^2.0.0",
"gulp": "^4.0.2", "gulp": "^4.0.2",
"gulp-clean-css": "^4.3.0", "gulp-clean-css": "^4.3.0",
"gulp-concat": "^2.6.1", "gulp-concat": "^2.6.1",
"gulp-sass": "^4.1.0", "gulp-sass": "^4.1.0",
"gulp-uglify": "^3.0.2", "gulp-uglify": "^3.0.2",
"vis-network": "^7.10.0",
"keycharm": "^0.3.0", "keycharm": "^0.3.0",
"moment": "^2.24.0", "moment": "^2.24.0",
"timsort": "^0.3.0", "timsort": "^0.3.0",
"vis-data": "^6.2.1",
"vis-util": "^4.0.0",
"uuid": "7.0.0", "uuid": "7.0.0",
"@egjs/hammerjs" : "^2.0.0" "vis-data": "^6.2.1",
"vis-network": "^7.10.2",
"vis-util": "^4.0.0"
}, },
"peerDependencies": { "peerDependencies": {}
}
} }
+1 -1
View File
@@ -3,7 +3,7 @@ from setuptools import setup, find_packages
setup( setup(
name='netbox-topology-views', name='netbox-topology-views',
version='0.4.10', version='0.5.3',
description='An NetBox plugin to create Topology maps', description='An NetBox plugin to create Topology maps',
url='https://github.com/mattieserver/netbox-topology-views', url='https://github.com/mattieserver/netbox-topology-views',
author='Mattijs Vanhaverbeke', author='Mattijs Vanhaverbeke',