Feature: Add customisable icons in topology (#193)

* [up] add config for custom images, better js

* [up] use bundler to bundle js

* [fix] remove domcontentloaded since defer is used

* [fix] formatting with black

* [fix] images drf api

* [up] add support for custom icons on additional roles: power panel, power feed, circuit

* [up] optimize topology generation by using `_id` when trying to access pk of related object

* [fix] kebab case instead of slugification

* [fix] use empty queryset in api views & change coord save logic
This commit is contained in:
Victor Gorchilov
2022-12-09 13:40:39 +01:00
committed by GitHub
parent 5c87694b87
commit 52c2611e9d
30 changed files with 1395 additions and 628 deletions
@@ -0,0 +1,46 @@
{% extends 'base/layout.html' %}
{% load buttons %}
{% load render_table from django_tables2 %}
{% load helpers %}
{% load static %}
{% block title %}Topology Views Images{% endblock %}
{% block head %}
<link rel="stylesheet" href="{% static 'netbox_topology_views/css/app.css' %}">
{% endblock %}
{% block content-wrapper %}
<form id="images" class="container py-4">
<div class="d-flex flex-wrap justify-content-center gap-3 mb-2">
{% for role in roles %}
<div class="d-flex flex-column align-items-center">
<div class="image-dropdown dropdown">
<button class="btn btn-secondary" type="button" id="dropdownMenuButton{{ role.id }}" data-bs-toggle="dropdown" aria-expanded="false">
{% if role.image %}
<img src="{{ role.image }}" />
{% else %}
Image
{% endif %}
</button>
<div class="dropdown-menu mt-2" aria-labelledby="dropdownMenuButton{{ role.id }}">
<div class="image-dropdown-content">
{% for image in images %}
<img src="{{ image.url }}" title="{{ image.title }}" width="64" data-role="{{ role.id }}" data-image="{{ image.url }}"/>
{% endfor %}
</div>
</div>
</div>
<span>{{ role.name }}</span>
</div>
{% endfor %}
</div>
<button class="btn btn-primary" type="submit">Save</button>
</form>
{% include 'netbox_topology_views/toasts.html' %}
{% endblock content-wrapper %}
{% block javascript %}
<script src="{% static 'netbox_topology_views/js/images.js' %}" defer></script>
{% endblock javascript %}
@@ -50,12 +50,8 @@
<div class="tab-pane show active" id="networks" role="tabpanel" aria-labelledby="network-tab">
<div class="panel-body">
<div id="visgraph" class=""></div>
<div id="visgraph"></div>
</div>
<script type="text/javascript">
var topology_data = {{ topology_data | safe }};
</script>
</div>
{% if filter_form %}
@@ -69,5 +65,9 @@
{% endblock content-wrapper %}
{% block javascript %}
<script src="{% static 'netbox_topology_views/js/app.js' %}"></script>
<script type="text/javascript">
const brokenImage = '{{ broken_image }}';
const topologyData = {{ topology_data | safe }};
</script>
<script src="{% static 'netbox_topology_views/js/app.js' %}" defer></script>
{% endblock javascript %}
@@ -0,0 +1,44 @@
<div id="django-messages" class="toast-container">
<div
id="topology-plugin-error-toast"
class="toast align-items-center border-0 bg-danger hide"
role="alert"
aria-live="assertive"
aria-atomic="true"
data-bs-delay="2000"
>
<div class="d-flex">
<div class="toast-body">
😢
<span>Error</span>
</div>
<button
type="button"
class="btn-close me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"
></button>
</div>
</div>
<div
id="topology-plugin-success-toast"
class="toast align-items-center border-0 bg-success hide"
role="alert"
aria-live="assertive"
aria-atomic="true"
data-bs-delay="2000"
>
<div class="d-flex">
<div class="toast-body">
👍
<span>Success</span>
</div>
<button
type="button"
class="btn-close me-2 m-auto"
data-bs-dismiss="toast"
aria-label="Close"
></button>
</div>
</div>
</div>