mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
* Replace masonry with gridstack * Initial work on dashboard widgets * Implement function to save dashboard layout * Define a default dashboard * Clean up widgets * Implement widget configuration views & forms * Permit merging dict value with existing dict in user config * Add widget deletion view * Enable HTMX for widget configuration * Implement view to add dashboard widgets * ObjectCountsWidget: Identify models by app_label & name * Add color customization to dashboard widgets * Introduce Dashboard model to store user dashboard layout & config * Clean up utility functions * Remove hard-coded API URL * Use fixed grid cell height * Add modal close button * Clean up dashboard views * Rebuild JS
This commit is contained in:
37
netbox/templates/extras/dashboard/widget.html
Normal file
37
netbox/templates/extras/dashboard/widget.html
Normal file
@@ -0,0 +1,37 @@
|
||||
{% load dashboard %}
|
||||
|
||||
<div
|
||||
class="grid-stack-item"
|
||||
gs-w="{{ widget.width }}"
|
||||
gs-h="{{ widget.height }}"
|
||||
gs-x="{{ widget.x }}"
|
||||
gs-y="{{ widget.y }}"
|
||||
gs-id="{{ widget.id }}"
|
||||
>
|
||||
<div class="card grid-stack-item-content">
|
||||
<div class="card-header text-center text-light bg-{% if widget.color %}{{ widget.color }}{% else %}secondary{% endif %} p-1">
|
||||
<div class="float-start ps-1">
|
||||
<a href="#"
|
||||
hx-get="{% url 'extras:dashboardwidget_config' id=widget.id %}"
|
||||
hx-target="#htmx-modal-content"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#htmx-modal"
|
||||
><i class="mdi mdi-cog text-gray"></i></a>
|
||||
</div>
|
||||
<div class="float-end pe-1">
|
||||
<a href="#"
|
||||
hx-get="{% url 'extras:dashboardwidget_delete' id=widget.id %}"
|
||||
hx-target="#htmx-modal-content"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#htmx-modal"
|
||||
><i class="mdi mdi-close text-gray"></i></a>
|
||||
</div>
|
||||
{% if widget.title %}
|
||||
<strong>{{ widget.title }}</strong>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="card-body p-2">
|
||||
{% render_widget widget %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
27
netbox/templates/extras/dashboard/widget_add.html
Normal file
27
netbox/templates/extras/dashboard/widget_add.html
Normal file
@@ -0,0 +1,27 @@
|
||||
{% load form_helpers %}
|
||||
|
||||
<form hx-post="{% url 'extras:dashboardwidget_add' %}" id="widget_add_form">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Add a Widget</h5>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% block form %}
|
||||
{% render_field widget_form.widget_class %}
|
||||
<div class="row mb-3">
|
||||
<label class="col-sm-3 col-form-label text-lg-end">Description</label>
|
||||
<div class="col">
|
||||
<div class="form-control-plaintext">{{ widget_class.description|placeholder }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{% render_field widget_form.color %}
|
||||
{% render_field widget_form.title %}
|
||||
{% render_form config_form %}
|
||||
{% endblock form %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{% block buttons %}
|
||||
<button class="btn btn-primary">Save</button>
|
||||
{% endblock buttons %}
|
||||
</div>
|
||||
</form>
|
20
netbox/templates/extras/dashboard/widget_config.html
Normal file
20
netbox/templates/extras/dashboard/widget_config.html
Normal file
@@ -0,0 +1,20 @@
|
||||
{% load form_helpers %}
|
||||
|
||||
<form hx-post="{{ form_url }}">
|
||||
{% csrf_token %}
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Widget Configuration</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
{% block form %}
|
||||
{% render_form widget_form %}
|
||||
{% render_form config_form %}
|
||||
{% endblock form %}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{% block buttons %}
|
||||
<button class="btn btn-primary">Save</button>
|
||||
{% endblock buttons %}
|
||||
</div>
|
||||
</form>
|
4
netbox/templates/extras/dashboard/widgets/changelog.html
Normal file
4
netbox/templates/extras/dashboard/widgets/changelog.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<div class="htmx-container"
|
||||
hx-get="{% url 'extras:objectchange_list' %}?sort=-time"
|
||||
hx-trigger="load"
|
||||
></div>
|
14
netbox/templates/extras/dashboard/widgets/objectcounts.html
Normal file
14
netbox/templates/extras/dashboard/widgets/objectcounts.html
Normal file
@@ -0,0 +1,14 @@
|
||||
{% load helpers %}
|
||||
|
||||
{% if counts %}
|
||||
<div class="list-group list-group-flush">
|
||||
{% for model, count in counts %}
|
||||
<a href="{% url model|viewname:"list" %}" class="list-group-item list-group-item-action">
|
||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||
{{ model|meta:"verbose_name_plural"|bettertitle }}
|
||||
<h6 class="mb-1">{{ count }}</h6>
|
||||
</div>
|
||||
</a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
@@ -3,80 +3,48 @@
|
||||
{% load render_table from django_tables2 %}
|
||||
|
||||
{% block header %}
|
||||
{% if new_release %}
|
||||
{# new_release is set only if the current user is a superuser or staff member #}
|
||||
<div class="header-alert-container">
|
||||
<div class="alert alert-info text-center mw-md-50" role="alert">
|
||||
<h6 class="alert-heading">
|
||||
<i class="mdi mdi-information-outline"></i><br/>New Release Available
|
||||
</h6>
|
||||
<small><a href="{{ new_release.url }}">NetBox v{{ new_release.version }}</a> is available.</small>
|
||||
<hr class="my-2" />
|
||||
<small class="mb-0">
|
||||
<a href="https://docs.netbox.dev/en/stable/installation/upgrading/">Upgrade Instructions</a>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if new_release %}
|
||||
{# new_release is set only if the current user is a superuser or staff member #}
|
||||
<div class="header-alert-container">
|
||||
<div class="alert alert-info text-center mw-md-50" role="alert">
|
||||
<h6 class="alert-heading">
|
||||
<i class="mdi mdi-information-outline"></i><br/>New Release Available
|
||||
</h6>
|
||||
<small><a href="{{ new_release.url }}">NetBox v{{ new_release.version }}</a> is available.</small>
|
||||
<hr class="my-2" />
|
||||
<small class="mb-0">
|
||||
<a href="https://docs.netbox.dev/en/stable/installation/upgrading/">Upgrade Instructions</a>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block title %}Home{% endblock %}
|
||||
|
||||
{% block content-wrapper %}
|
||||
<div class="px-3">
|
||||
{# General stats #}
|
||||
<div class="row masonry">
|
||||
{% for section, items, icon in stats %}
|
||||
<div class="col col-sm-12 col-lg-6 col-xl-4 my-2 masonry-item">
|
||||
<div class="card">
|
||||
<h6 class="card-header text-center">
|
||||
<i class="mdi mdi-{{ icon }}"></i>
|
||||
<span class="ms-1">{{ section }}</span>
|
||||
</h6>
|
||||
<div class="card-body">
|
||||
<div class="list-group list-group-flush">
|
||||
{% for item in items %}
|
||||
{% if item.permission in perms %}
|
||||
<a href="{% url item.viewname %}" class="list-group-item list-group-item-action">
|
||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||
{{ item.label }}
|
||||
<h4 class="mb-1">{{ item.count }}</h4>
|
||||
</div>
|
||||
</a>
|
||||
{% else %}
|
||||
<li class="list-group-item list-group-item-action disabled">
|
||||
<div class="d-flex w-100 justify-content-between align-items-center">
|
||||
{{ item.label }}
|
||||
<h4 class="mb-1">
|
||||
<i title="No permission" class="mdi mdi-lock"></i>
|
||||
</h4>
|
||||
</div>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{# Changelog #}
|
||||
{% if perms.extras.view_objectchange %}
|
||||
<div class="row my-4 flex-grow-1 changelog-container">
|
||||
<div class="col">
|
||||
<div class="card">
|
||||
<h6 class="card-header text-center">
|
||||
<i class="mdi mdi-clipboard-clock"></i>
|
||||
<span class="ms-1">Change Log</span>
|
||||
</h6>
|
||||
<div class="card-body htmx-container table-responsive"
|
||||
hx-get="{% url 'extras:objectchange_list' %}?sort=-time"
|
||||
hx-trigger="load"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
{# Render the user's customized dashboard #}
|
||||
<div class="grid-stack">
|
||||
{% for widget in dashboard %}
|
||||
{% include 'extras/dashboard/widget.html' %}
|
||||
{% endfor %}
|
||||
</div>
|
||||
<div class="text-end px-2">
|
||||
<a href="#"
|
||||
hx-get="{% url 'extras:dashboardwidget_add' %}"
|
||||
hx-target="#htmx-modal-content"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#htmx-modal"
|
||||
class="btn btn-success btn-sm"
|
||||
>
|
||||
<i class="mdi mdi-plus"></i> Add Widget
|
||||
</a>
|
||||
<button id="save_dashboard" class="btn btn-primary btn-sm" data-url="{% url 'extras-api:dashboard' %}">
|
||||
<i class="mdi mdi-content-save-outline"></i> Save
|
||||
</button>
|
||||
</div>
|
||||
{% endblock content-wrapper %}
|
||||
|
||||
{% block modals %}
|
||||
{% include 'inc/htmx_modal.html' %}
|
||||
{% endblock modals %}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<div class="modal fade" id="htmx-modal" tabindex="-1" aria-hidden="true">
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content" id="htmx-modal-content">
|
||||
{# Dynamic content goes here #}
|
||||
</div>
|
||||
|
Reference in New Issue
Block a user