* Add resize listener and height calculation * Fixed typos * add permissions for new views
This commit is contained in:
@@ -201,3 +201,12 @@ Set `Coordinate Groups` according to your needs:
|
|||||||
|
|
||||||
Set `Coordinates` according to your needs:
|
Set `Coordinates` according to your needs:
|
||||||
+ netbox_topology_views | coordinate | view/add/change/delete
|
+ netbox_topology_views | coordinate | view/add/change/delete
|
||||||
|
|
||||||
|
Set `Power Feed Coordinates` according to your needs:
|
||||||
|
+ netbox_topology_views | power feed coordinate | view/add/change/delete
|
||||||
|
|
||||||
|
Set `Power Panel Coordinates` according to your needs:
|
||||||
|
+ netbox_topology_views | power panel coordinate | view/add/change/delete
|
||||||
|
|
||||||
|
Set `Circuit Coordinates` according to your needs:
|
||||||
|
+ netbox_topology_views | circuit coordinate | view/add/change/delete
|
||||||
|
|||||||
@@ -139,8 +139,8 @@ class SaveRoleImageViewSet(PermissionRequiredMixin, ReadOnlyModelViewSet):
|
|||||||
queryset = DeviceRole.objects.none()
|
queryset = DeviceRole.objects.none()
|
||||||
serializer_class = RoleImageSerializer
|
serializer_class = RoleImageSerializer
|
||||||
permission_required = (
|
permission_required = (
|
||||||
"dcim.add_device_role",
|
"dcim.add_devicerole",
|
||||||
"dcim.change_device_role",
|
"dcim.change_devicerole",
|
||||||
)
|
)
|
||||||
|
|
||||||
@action(detail=False, methods=["post"])
|
@action(detail=False, methods=["post"])
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ menu = PluginMenu(
|
|||||||
),
|
),
|
||||||
('PREFERENCES',
|
('PREFERENCES',
|
||||||
(
|
(
|
||||||
PluginMenuItem(link="plugins:netbox_topology_views:images", link_text="Images", permissions=[ "dcim.view_site","dcim.view_device_role"]),
|
PluginMenuItem(link="plugins:netbox_topology_views:images", link_text="Images", permissions=[ "dcim.view_site","dcim.view_devicerole"]),
|
||||||
PluginMenuItem(link="plugins:netbox_topology_views:individualoptions", link_text="Individual Options", permissions=['netbox_topology_views.change_individualoptions']),
|
PluginMenuItem(link="plugins:netbox_topology_views:individualoptions", link_text="Individual Options", permissions=['netbox_topology_views.change_individualoptions']),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1 +1,23 @@
|
|||||||
#visgraph{height:64vh}html[data-netbox-color-mode=dark] #visgraph{background-color:#212529}.image-dropdown img{width:64px;height:64px}.image-dropdown-content{display:flex;flex-wrap:wrap;gap:.5rem;padding-inline:.5rem;width:50vw;max-width:32rem}.image-dropdown-content>img{cursor:pointer}
|
#visgraph {
|
||||||
|
height:64vh;
|
||||||
|
border: 1px solid #ced4da
|
||||||
|
}
|
||||||
|
html[data-netbox-color-mode=dark]
|
||||||
|
#visgraph {
|
||||||
|
background-color:#212529;
|
||||||
|
border: 1px solid #495057
|
||||||
|
}
|
||||||
|
.image-dropdown img {
|
||||||
|
width:64px;height:64px
|
||||||
|
}
|
||||||
|
.image-dropdown-content {
|
||||||
|
display:flex;
|
||||||
|
flex-wrap:wrap;
|
||||||
|
gap:.5rem;
|
||||||
|
padding-inline:.5rem;
|
||||||
|
width:50vw;
|
||||||
|
max-width:32rem
|
||||||
|
}
|
||||||
|
.image-dropdown-content>img {
|
||||||
|
cursor:pointer
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
{% endblock controls %}
|
{% endblock controls %}
|
||||||
|
|
||||||
{% block tabs %}
|
{% block tabs %}
|
||||||
<ul class="nav nav-tabs px-3">
|
<ul class="nav nav-tabs px-3" id="tabswrapper">
|
||||||
{% block tab_items %}
|
{% block tab_items %}
|
||||||
<li class="nav-item" role="presentation">
|
<li class="nav-item" role="presentation">
|
||||||
<button class="nav-link active" id="network-tab" data-bs-toggle="tab" data-bs-target="#networks" type="button" role="tab" aria-controls="filters-form" aria-selected="true">
|
<button class="nav-link active" id="network-tab" data-bs-toggle="tab" data-bs-target="#networks" type="button" role="tab" aria-controls="filters-form" aria-selected="true">
|
||||||
@@ -50,11 +50,13 @@
|
|||||||
|
|
||||||
{% block content-wrapper %}
|
{% block content-wrapper %}
|
||||||
{% with config=settings.PLUGINS_CONFIG.netbox_topology_views %}
|
{% with config=settings.PLUGINS_CONFIG.netbox_topology_views %}
|
||||||
<div class="tab-content">
|
<div class="tab-content" id="tabcontentwrapper">
|
||||||
|
|
||||||
{# Applied filters #}
|
{# Applied filters #}
|
||||||
{% if filter_form %}
|
{% if filter_form %}
|
||||||
{% applied_filters model filter_form request.GET %}
|
<div id="filterwrapper">
|
||||||
|
{% applied_filters model filter_form request.GET %}
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<div class="tab-pane show active" id="networks" role="tabpanel" aria-labelledby="network-tab">
|
<div class="tab-pane show active" id="networks" role="tabpanel" aria-labelledby="network-tab">
|
||||||
@@ -78,6 +80,36 @@
|
|||||||
const brokenImage = '{{ broken_image }}';
|
const brokenImage = '{{ broken_image }}';
|
||||||
const topologyData = {{ topology_data | safe }};
|
const topologyData = {{ topology_data | safe }};
|
||||||
const basePath = '{{ basepath }}';
|
const basePath = '{{ basepath }}';
|
||||||
</script>
|
|
||||||
|
window.addEventListener("resize", resizeCanvas);
|
||||||
|
resizeCanvas();
|
||||||
|
|
||||||
|
function resizeCanvas() {
|
||||||
|
heightToSubtract = getElementHeight('.navbar') +
|
||||||
|
getElementHeight('.title-container') +
|
||||||
|
getElementHeight('#tabswrapper') +
|
||||||
|
getElementHeight('#filterwrapper') +
|
||||||
|
getElementHeight('.footer') +
|
||||||
|
getElementPadding('#tabcontentwrapper');
|
||||||
|
|
||||||
|
document.getElementById("visgraph").style.height = "calc(100vh - " + heightToSubtract + "px)";
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementPadding(element) {
|
||||||
|
el = document.querySelector(element);
|
||||||
|
els = getComputedStyle(el);
|
||||||
|
padding = parseInt(els.paddingTop) + parseInt(els.paddingBottom);
|
||||||
|
|
||||||
|
return padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getElementHeight(element) {
|
||||||
|
el = document.querySelector(element);
|
||||||
|
els = getComputedStyle(el);
|
||||||
|
height = el.offsetHeight + parseInt(els.marginTop) + parseInt(els.marginBottom);
|
||||||
|
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<script src="{% static 'netbox_topology_views/js/app.js' %}" defer></script>
|
<script src="{% static 'netbox_topology_views/js/app.js' %}" defer></script>
|
||||||
{% endblock javascript %}
|
{% endblock javascript %}
|
||||||
|
|||||||
@@ -771,9 +771,9 @@ ADDITIONAL_ROLES = (PowerPanel, PowerFeed, Circuit)
|
|||||||
class TopologyImagesView(PermissionRequiredMixin, View):
|
class TopologyImagesView(PermissionRequiredMixin, View):
|
||||||
permission_required = (
|
permission_required = (
|
||||||
"dcim.view_site",
|
"dcim.view_site",
|
||||||
"dcim.view_device_role",
|
"dcim.view_devicerole",
|
||||||
"dcim.add_device_role",
|
"dcim.add_devicerole",
|
||||||
"dcim.change_device_role",
|
"dcim.change_devicerole",
|
||||||
)
|
)
|
||||||
|
|
||||||
def get(self, request: HttpRequest):
|
def get(self, request: HttpRequest):
|
||||||
|
|||||||
Reference in New Issue
Block a user