Add Coordinate models, forms, views, templates,...
This commit is contained in:
@@ -2,7 +2,7 @@ from dcim.models import Device, DeviceRole
|
|||||||
from rest_framework.serializers import ModelSerializer
|
from rest_framework.serializers import ModelSerializer
|
||||||
from netbox.api.serializers import NetBoxModelSerializer
|
from netbox.api.serializers import NetBoxModelSerializer
|
||||||
|
|
||||||
from netbox_topology_views.models import RoleImage, IndividualOptions
|
from netbox_topology_views.models import RoleImage, IndividualOptions, CoordinateGroups, Coordinates
|
||||||
|
|
||||||
|
|
||||||
class TopologyDummySerializer(ModelSerializer):
|
class TopologyDummySerializer(ModelSerializer):
|
||||||
@@ -22,6 +22,16 @@ class DeviceRoleSerializer(ModelSerializer):
|
|||||||
model = DeviceRole
|
model = DeviceRole
|
||||||
fields = ("name", "slug", "color", "vm_role", "description")
|
fields = ("name", "slug", "color", "vm_role", "description")
|
||||||
|
|
||||||
|
class CoordinateGroupsSerializer(NetBoxModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = CoordinateGroups
|
||||||
|
fields = ("name", "description")
|
||||||
|
|
||||||
|
class CoordinatesSerializer(NetBoxModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Coordinates
|
||||||
|
fields = ("x", "y")
|
||||||
|
|
||||||
class IndividualOptionsSerializer(NetBoxModelSerializer):
|
class IndividualOptionsSerializer(NetBoxModelSerializer):
|
||||||
class Meta:
|
class Meta:
|
||||||
model = IndividualOptions
|
model = IndividualOptions
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import django_filters
|
import django_filters
|
||||||
from dcim.choices import DeviceStatusChoices
|
from dcim.choices import DeviceStatusChoices
|
||||||
from dcim.models import Device, DeviceRole, Location, Rack, Region, Site
|
from dcim.models import Device, DeviceRole, Location, Rack, Region, Site
|
||||||
|
from .models import Coordinates
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from netbox.filtersets import NetBoxModelFilterSet
|
from netbox.filtersets import NetBoxModelFilterSet
|
||||||
from tenancy.filtersets import TenancyFilterSet
|
from tenancy.filtersets import TenancyFilterSet
|
||||||
@@ -53,3 +54,15 @@ class DeviceFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
|
|||||||
return queryset
|
return queryset
|
||||||
qs_filter = Q(name__icontains=value)
|
qs_filter = Q(name__icontains=value)
|
||||||
return queryset.filter(qs_filter)
|
return queryset.filter(qs_filter)
|
||||||
|
|
||||||
|
class CoordinateFilterSet(NetBoxModelFilterSet):
|
||||||
|
class Meta:
|
||||||
|
model = Coordinates
|
||||||
|
fields = ('id', 'group', 'device', 'x', 'y')
|
||||||
|
|
||||||
|
def search(self, queryset, name, value):
|
||||||
|
"""Perform the filtered search."""
|
||||||
|
if not value.strip():
|
||||||
|
return queryset
|
||||||
|
qs_filter = Q(group__icontains=value | Q(device__icontains=value))
|
||||||
|
return queryset.filter(qs_filter)
|
||||||
@@ -15,12 +15,13 @@ from django.conf import settings
|
|||||||
from netbox.forms import NetBoxModelFilterSetForm, NetBoxModelForm
|
from netbox.forms import NetBoxModelFilterSetForm, NetBoxModelForm
|
||||||
from utilities.forms.fields import (
|
from utilities.forms.fields import (
|
||||||
TagFilterField,
|
TagFilterField,
|
||||||
|
DynamicModelChoiceField,
|
||||||
DynamicModelMultipleChoiceField,
|
DynamicModelMultipleChoiceField,
|
||||||
MultipleChoiceField
|
MultipleChoiceField
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
from .models import IndividualOptions
|
from .models import IndividualOptions, CoordinateGroups, Coordinates
|
||||||
|
|
||||||
class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
||||||
model = Device
|
model = Device
|
||||||
@@ -141,6 +142,55 @@ class DeviceFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
|
|||||||
label =_("Show Wireless Links"), required=False, initial=False
|
label =_("Show Wireless Links"), required=False, initial=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class CoordinateGroupsForm(NetBoxModelForm):
|
||||||
|
fieldsets = (
|
||||||
|
('Group Details', ('name', 'description')),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = CoordinateGroups
|
||||||
|
fields = ('name', 'description')
|
||||||
|
|
||||||
|
class CoordinatesForm(NetBoxModelForm):
|
||||||
|
fieldsets = (
|
||||||
|
('Coordinates', ('group', 'device', 'x', 'y')),
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Coordinates
|
||||||
|
fields = ('group', 'device', 'x', 'y')
|
||||||
|
|
||||||
|
class CoordinatesFilterForm(NetBoxModelFilterSetForm):
|
||||||
|
model = Coordinates
|
||||||
|
|
||||||
|
group = forms.ModelMultipleChoiceField(
|
||||||
|
queryset=CoordinateGroups.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
device = DynamicModelChoiceField(
|
||||||
|
queryset=Device.objects.all(),
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
id = DynamicModelMultipleChoiceField(
|
||||||
|
queryset=Device.objects.all(),
|
||||||
|
required=False,
|
||||||
|
label=_("Device"),
|
||||||
|
query_params={
|
||||||
|
"location_id": "$location_id",
|
||||||
|
"region_id": "$region_id",
|
||||||
|
"site_id": "$site_id",
|
||||||
|
"role_id": "$device_role_id",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
x = forms.IntegerField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
|
y = forms.IntegerField(
|
||||||
|
required=False
|
||||||
|
)
|
||||||
|
|
||||||
class IndividualOptionsForm(NetBoxModelForm):
|
class IndividualOptionsForm(NetBoxModelForm):
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(
|
(
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
# Generated by Django 4.1.8 on 2023-05-01 08:21
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import taggit.managers
|
||||||
|
import utilities.json
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('dcim', '0171_cabletermination_change_logging'),
|
||||||
|
('extras', '0092_delete_jobresult'),
|
||||||
|
('netbox_topology_views', '0003_individualoptions_show_neighbors'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='CoordinateGroups',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
|
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
||||||
|
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
|
||||||
|
('name', models.CharField(max_length=100, unique=True)),
|
||||||
|
('description', models.CharField(blank=True, max_length=255)),
|
||||||
|
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['name'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Coordinates',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
|
||||||
|
('created', models.DateTimeField(auto_now_add=True, null=True)),
|
||||||
|
('last_updated', models.DateTimeField(auto_now=True, null=True)),
|
||||||
|
('custom_field_data', models.JSONField(blank=True, default=dict, encoder=utilities.json.CustomFieldJSONEncoder)),
|
||||||
|
('x', models.IntegerField()),
|
||||||
|
('y', models.IntegerField()),
|
||||||
|
('device', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='dcim.device')),
|
||||||
|
('group', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='netbox_topology_views.coordinategroups')),
|
||||||
|
('tags', taggit.managers.TaggableManager(through='extras.TaggedItem', to='extras.Tag')),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['group', 'device'],
|
||||||
|
'unique_together': {('device', 'group')},
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from dcim.models import DeviceRole
|
from dcim.models import Device, DeviceRole
|
||||||
from extras.models import Tag
|
from extras.models import Tag
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.templatetags.static import static
|
from django.templatetags.static import static
|
||||||
|
from django.urls import reverse
|
||||||
from netbox.models import NetBoxModel
|
from netbox.models import NetBoxModel
|
||||||
from netbox.models.features import (
|
from netbox.models.features import (
|
||||||
ChangeLoggingMixin,
|
ChangeLoggingMixin,
|
||||||
@@ -94,6 +95,63 @@ class RoleImage(ChangeLoggingMixin, ExportTemplatesMixin, WebhooksMixin):
|
|||||||
return self.get_default_image(dir)
|
return self.get_default_image(dir)
|
||||||
return static(f"/{self.image}")
|
return static(f"/{self.image}")
|
||||||
|
|
||||||
|
class CoordinateGroups(NetBoxModel):
|
||||||
|
"""
|
||||||
|
A coordinate group is used to display the topology for a particular group.
|
||||||
|
This allows different visualizations with the same devices.
|
||||||
|
"""
|
||||||
|
name = models.CharField(
|
||||||
|
max_length=100,
|
||||||
|
unique=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
description = models.CharField(
|
||||||
|
max_length=255,
|
||||||
|
blank = True,
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['name']
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse('plugins:netbox_topology_views:coordinategroups', args=[self.pk])
|
||||||
|
|
||||||
|
class Coordinates(NetBoxModel):
|
||||||
|
"""
|
||||||
|
Coordinates are being used to place devices in a topology view onto a certian
|
||||||
|
position. Devices belong to one or more coordinate groups. They have to
|
||||||
|
be unique together.
|
||||||
|
"""
|
||||||
|
device = models.ForeignKey(Device, on_delete=models.CASCADE)
|
||||||
|
group = models.ForeignKey(CoordinateGroups, on_delete=models.CASCADE)
|
||||||
|
|
||||||
|
x = models.IntegerField(
|
||||||
|
help_text='X-coordinate of the device (horizontal) on the canvas. '
|
||||||
|
'Smaller values correspond to a position further up on the monitor.',
|
||||||
|
)
|
||||||
|
y = models.IntegerField(
|
||||||
|
help_text='Y-coordinate of the device (vertical) on the canvas. '
|
||||||
|
'Smaller values correspond to a position further to the left on the monitor.',
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['group', 'device']
|
||||||
|
unique_together = ('device', 'group')
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f'{self.x};{self.y}'
|
||||||
|
|
||||||
|
def get_absolute_url(self):
|
||||||
|
return reverse('plugins:netbox_topology_views:coordinates', args=[self.pk])
|
||||||
|
|
||||||
|
def set_xy_from_text_coords(self, coords: str):
|
||||||
|
xy = coords.split(';')
|
||||||
|
self.x = xy[0]
|
||||||
|
self.y = xy[1]
|
||||||
|
|
||||||
class IndividualOptions(NetBoxModel):
|
class IndividualOptions(NetBoxModel):
|
||||||
CHOICES = (
|
CHOICES = (
|
||||||
('interface', 'interface'),
|
('interface', 'interface'),
|
||||||
|
|||||||
@@ -1,10 +1,35 @@
|
|||||||
from extras.plugins import PluginMenu, PluginMenuItem
|
from extras.plugins import PluginMenu, PluginMenuItem, PluginMenuButton
|
||||||
|
from utilities.choices import ButtonColorChoices
|
||||||
|
|
||||||
|
coordinategroups_buttons = [
|
||||||
|
PluginMenuButton(
|
||||||
|
link='plugins:netbox_topology_views:coordinategroups_add',
|
||||||
|
title='Add',
|
||||||
|
icon_class='mdi mdi-plus-thick',
|
||||||
|
color=ButtonColorChoices.GREEN,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
|
coordinates_buttons = [
|
||||||
|
PluginMenuButton(
|
||||||
|
link='plugins:netbox_topology_views:coordinates_add',
|
||||||
|
title='Add',
|
||||||
|
icon_class='mdi mdi-plus-thick',
|
||||||
|
color=ButtonColorChoices.GREEN,
|
||||||
|
)
|
||||||
|
]
|
||||||
|
|
||||||
menu = PluginMenu(
|
menu = PluginMenu(
|
||||||
label='Topology Views',
|
label='Topology Views',
|
||||||
icon_class="mdi mdi-sitemap",
|
icon_class="mdi mdi-sitemap",
|
||||||
groups=(
|
groups=(
|
||||||
('TOPOLOGY', (PluginMenuItem(link="plugins:netbox_topology_views:home", link_text="Topology"),),),
|
('TOPOLOGY',
|
||||||
|
(
|
||||||
|
PluginMenuItem(link="plugins:netbox_topology_views:home", link_text="Topology"),
|
||||||
|
PluginMenuItem(link="plugins:netbox_topology_views:coordinategroups_list", link_text="Coordinate Groups", buttons=coordinategroups_buttons),
|
||||||
|
PluginMenuItem(link="plugins:netbox_topology_views:coordinates_list", link_text="Coordinates", buttons=coordinates_buttons),
|
||||||
|
),
|
||||||
|
),
|
||||||
('PREFERENCES',
|
('PREFERENCES',
|
||||||
(
|
(
|
||||||
PluginMenuItem(link="plugins:netbox_topology_views:images", link_text="Images"),
|
PluginMenuItem(link="plugins:netbox_topology_views:images", link_text="Images"),
|
||||||
|
|||||||
@@ -0,0 +1,18 @@
|
|||||||
|
from netbox.search import SearchIndex, register_search
|
||||||
|
from .models import CoordinateGroups, Coordinates
|
||||||
|
|
||||||
|
@register_search
|
||||||
|
class CoordinateGroupsIndex(SearchIndex):
|
||||||
|
model = CoordinateGroups
|
||||||
|
fields = (
|
||||||
|
('name', 100),
|
||||||
|
('description', 2000),
|
||||||
|
)
|
||||||
|
|
||||||
|
@register_search
|
||||||
|
class CoordinatesIndex(SearchIndex):
|
||||||
|
model = Coordinates
|
||||||
|
fields = (
|
||||||
|
('group', 100),
|
||||||
|
('device', 200),
|
||||||
|
)
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import django_tables2 as tables
|
||||||
|
|
||||||
|
from netbox.tables import NetBoxTable, ChoiceFieldColumn
|
||||||
|
from .models import CoordinateGroups, Coordinates
|
||||||
|
|
||||||
|
class CoordinateGroupListTable(NetBoxTable):
|
||||||
|
name = tables.Column(
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta(NetBoxTable.Meta):
|
||||||
|
model = CoordinateGroups
|
||||||
|
fields = ('pk', 'name', 'description')
|
||||||
|
default_columns = ('name', 'description')
|
||||||
|
|
||||||
|
class CoordinateListTable(NetBoxTable):
|
||||||
|
group = tables.Column(
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
|
|
||||||
|
device = tables.Column(
|
||||||
|
linkify=True
|
||||||
|
)
|
||||||
|
|
||||||
|
class Meta(NetBoxTable.Meta):
|
||||||
|
model = Coordinates
|
||||||
|
fields = ('pk', 'group', 'device', 'x', 'y')
|
||||||
|
default_columns = ('id', 'group', 'device', 'x', 'y')
|
||||||
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load helpers %}
|
||||||
|
{% load plugins %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
|
{% block title %}Topology Views Coordinate Group{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Coordinate Group
|
||||||
|
</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">Description</th>
|
||||||
|
<td>{{ object.description|placeholder }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% plugin_left_page object %}
|
||||||
|
</div>
|
||||||
|
<div class="col col-md-6">
|
||||||
|
{% include 'inc/panels/custom_fields.html' %}
|
||||||
|
{% plugin_right_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% extends 'generic/object_edit.html' %}
|
||||||
|
|
||||||
|
{% block title %}Add a new Coordinate Group{% endblock title %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% extends 'generic/object_edit.html' %}
|
||||||
|
|
||||||
|
{% block title %}Edit Coordinate Group{% endblock title %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% extends 'generic/object_list.html' %}
|
||||||
|
|
||||||
|
{% block title %}Coordinate Groups{% endblock title %}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
{% extends 'generic/object.html' %}
|
||||||
|
{% load helpers %}
|
||||||
|
{% load plugins %}
|
||||||
|
{% load render_table from django_tables2 %}
|
||||||
|
|
||||||
|
{% block title %}Topology Views Coordinates{% endblock title %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row mb-3">
|
||||||
|
<div class="col col-md-6">
|
||||||
|
<div class="card">
|
||||||
|
<h5 class="card-header">
|
||||||
|
Coordinates
|
||||||
|
</h5>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-hover attr-table">
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Group</th>
|
||||||
|
<td>{{ object.group }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Device</th>
|
||||||
|
<td>{{ object.device }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">X-Coordinate</th>
|
||||||
|
<td>{{ object.x }}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th scope="row">Y-Coordinate</th>
|
||||||
|
<td>{{ object.y }}</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% plugin_left_page object %}
|
||||||
|
</div>
|
||||||
|
<div class="col col-md-6">
|
||||||
|
{% include 'inc/panels/custom_fields.html' %}
|
||||||
|
{% plugin_right_page object %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock content %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% extends 'generic/object_edit.html' %}
|
||||||
|
|
||||||
|
{% block title %}Add new Device Coordinates{% endblock title %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% extends 'generic/object_edit.html' %}
|
||||||
|
|
||||||
|
{% block title %}Edit Device Coordinates{% endblock title %}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
{% extends 'generic/object_list.html' %}
|
||||||
|
|
||||||
|
{% block title %}Device Coordinates{% endblock title %}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from django.views.generic.base import RedirectView
|
from django.views.generic.base import RedirectView
|
||||||
|
|
||||||
from . import views
|
from . import models, views
|
||||||
|
|
||||||
# Define a list of URL patterns to be imported by NetBox. Each pattern maps a URL to
|
# Define a list of URL patterns to be imported by NetBox. Each pattern maps a URL to
|
||||||
# a specific view so that it can be accessed by users.
|
# a specific view so that it can be accessed by users.
|
||||||
@@ -10,4 +10,20 @@ urlpatterns = (
|
|||||||
path("topology/", views.TopologyHomeView.as_view(), name="home"),
|
path("topology/", views.TopologyHomeView.as_view(), name="home"),
|
||||||
path("images/", views.TopologyImagesView.as_view(), name="images"),
|
path("images/", views.TopologyImagesView.as_view(), name="images"),
|
||||||
path("individualoptions/", views.TopologyIndividualOptionsView.as_view(), name="individualoptions"),
|
path("individualoptions/", views.TopologyIndividualOptionsView.as_view(), name="individualoptions"),
|
||||||
|
|
||||||
|
# Coordinate Group
|
||||||
|
path("coordinate-groups/", views.CoordinateGroupListView.as_view(), name="coordinategroups_list"),
|
||||||
|
path("coordinate-groups/add/", views.CoordinateGroupAddView.as_view(), name="coordinategroups_add"),
|
||||||
|
path("coordinate-groups/<int:pk>/", views.CoordinateGroupView.as_view(), name="coordinategroups"),
|
||||||
|
path("coordinate-groups/<int:pk>/edit/", views.CoordinateGroupEditView.as_view(), name="coordinategroups_edit"),
|
||||||
|
path("coordinate-groups/<int:pk>/delete/", views.CoordinateGroupDeleteView.as_view(), name="coordinategroups_delete"),
|
||||||
|
path("coordinate-groups/<int:pk>/changelog/", views.CoordinateGroupChangeLogView.as_view(), name="coordinategroups_changelog", kwargs={'model': models.CoordinateGroups}),
|
||||||
|
|
||||||
|
# Coordinate
|
||||||
|
path("coordinates/", views.CoordinateListView.as_view(), name="coordinates_list"),
|
||||||
|
path("coordinates/add/", views.CoordinateAddView.as_view(), name="coordinates_add"),
|
||||||
|
path("coordinates/<int:pk>/", views.CoordinateView.as_view(), name="coordinates"),
|
||||||
|
path("coordinates/<int:pk>/edit/", views.CoordinateEditView.as_view(), name="coordinates_edit"),
|
||||||
|
path("coordinates/<int:pk>/delete/", views.CoordinateDeleteView.as_view(), name="coordinates_delete"),
|
||||||
|
path("coordinates/<int:pk>/changelog/", views.CoordinateChangeLogView.as_view(), name="coordinates_changelog", kwargs={'model': models.Coordinates}),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -29,10 +29,13 @@ from django.shortcuts import render
|
|||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
from extras.models import Tag
|
from extras.models import Tag
|
||||||
from wireless.models import WirelessLink
|
from wireless.models import WirelessLink
|
||||||
|
from netbox.views.generic import ObjectView, ObjectListView, ObjectEditView, ObjectDeleteView, ObjectChangeLogView
|
||||||
|
|
||||||
from netbox_topology_views.filters import DeviceFilterSet
|
|
||||||
from netbox_topology_views.forms import DeviceFilterForm, IndividualOptionsForm
|
from netbox_topology_views.filters import DeviceFilterSet, CoordinateFilterSet
|
||||||
from netbox_topology_views.models import RoleImage, IndividualOptions
|
from netbox_topology_views.forms import DeviceFilterForm, IndividualOptionsForm, CoordinateGroupsForm, CoordinatesForm, CoordinatesFilterForm
|
||||||
|
from netbox_topology_views.models import RoleImage, CoordinateGroups, Coordinates, IndividualOptions
|
||||||
|
from netbox_topology_views.tables import CoordinateGroupListTable, CoordinateListTable
|
||||||
from netbox_topology_views.utils import (
|
from netbox_topology_views.utils import (
|
||||||
CONF_IMAGE_DIR,
|
CONF_IMAGE_DIR,
|
||||||
find_image_url,
|
find_image_url,
|
||||||
@@ -751,6 +754,80 @@ class TopologyImagesView(PermissionRequiredMixin, View):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class CoordinateView(PermissionRequiredMixin, ObjectView):
|
||||||
|
permission_required = 'netbox_topology_views.view_coordinates'
|
||||||
|
|
||||||
|
queryset = Coordinates.objects.all()
|
||||||
|
|
||||||
|
class CoordinateAddView(PermissionRequiredMixin, ObjectEditView):
|
||||||
|
permission_required = 'netbox_topology_views.add_coordinates'
|
||||||
|
|
||||||
|
queryset = Coordinates.objects.all()
|
||||||
|
form = CoordinatesForm
|
||||||
|
template_name = 'netbox_topology_views/coordinates_add.html'
|
||||||
|
|
||||||
|
class CoordinateListView(PermissionRequiredMixin, ObjectListView):
|
||||||
|
permission_required = 'netbox_topology_views.view_coordinates'
|
||||||
|
|
||||||
|
queryset = Coordinates.objects.all()
|
||||||
|
table = CoordinateListTable
|
||||||
|
template_name = 'netbox_topology_views/coordinates_list.html'
|
||||||
|
filterset = CoordinateFilterSet
|
||||||
|
filterset_form = CoordinatesFilterForm
|
||||||
|
|
||||||
|
class CoordinateEditView(PermissionRequiredMixin, ObjectEditView):
|
||||||
|
permission_required = 'netbox_topology_views.change_coordinates'
|
||||||
|
|
||||||
|
queryset = Coordinates.objects.all()
|
||||||
|
form = CoordinatesForm
|
||||||
|
template_name = 'netbox_topology_views/coordinates_edit.html'
|
||||||
|
|
||||||
|
class CoordinateDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
|
permission_required = 'netbox_topology_views.delete_coordinates'
|
||||||
|
|
||||||
|
queryset = Coordinates.objects.all()
|
||||||
|
|
||||||
|
class CoordinateChangeLogView(PermissionRequiredMixin, ObjectChangeLogView):
|
||||||
|
permission_required = 'netbox_topology_views.view_coordinates'
|
||||||
|
|
||||||
|
queryset = Coordinates.objects.all()
|
||||||
|
|
||||||
|
class CoordinateGroupView(PermissionRequiredMixin, ObjectView):
|
||||||
|
permission_required = 'netbox_topology_views.view_coordinategroups'
|
||||||
|
|
||||||
|
queryset = CoordinateGroups.objects.all()
|
||||||
|
|
||||||
|
class CoordinateGroupAddView(PermissionRequiredMixin, ObjectEditView):
|
||||||
|
permission_required = 'netbox_topology_views.add_coordinategroups'
|
||||||
|
|
||||||
|
queryset = CoordinateGroups.objects.all()
|
||||||
|
form = CoordinateGroupsForm
|
||||||
|
template_name = 'netbox_topology_views/coordinategroups_add.html'
|
||||||
|
|
||||||
|
class CoordinateGroupListView(PermissionRequiredMixin, ObjectListView):
|
||||||
|
permission_required = 'netbox_topology_views.view_coordinategroups'
|
||||||
|
|
||||||
|
queryset = CoordinateGroups.objects.all()
|
||||||
|
table = CoordinateGroupListTable
|
||||||
|
template_name = 'netbox_topology_views/coordinategroups_list.html'
|
||||||
|
|
||||||
|
class CoordinateGroupEditView(PermissionRequiredMixin, ObjectEditView):
|
||||||
|
permission_required = 'netbox_topology_views.change_coordinategroups'
|
||||||
|
|
||||||
|
queryset = CoordinateGroups.objects.all()
|
||||||
|
form = CoordinateGroupsForm
|
||||||
|
template_name = 'netbox_topology_views/coordinategroups_edit.html'
|
||||||
|
|
||||||
|
class CoordinateGroupDeleteView(PermissionRequiredMixin, ObjectDeleteView):
|
||||||
|
permission_required = 'netbox_topology_views.delete_coordinategroups'
|
||||||
|
|
||||||
|
queryset = CoordinateGroups.objects.all()
|
||||||
|
|
||||||
|
class CoordinateGroupChangeLogView(PermissionRequiredMixin, ObjectChangeLogView):
|
||||||
|
permission_required = 'netbox_topology_views.view_coordinategroups'
|
||||||
|
|
||||||
|
queryset = CoordinateGroups.objects.all()
|
||||||
|
|
||||||
class TopologyIndividualOptionsView(PermissionRequiredMixin, View):
|
class TopologyIndividualOptionsView(PermissionRequiredMixin, View):
|
||||||
permission_required = 'netbox_topology_views.change_individualoptions'
|
permission_required = 'netbox_topology_views.change_individualoptions'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user