mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Implement view to add dashboard widgets
This commit is contained in:
parent
b6e17448ff
commit
98732f05aa
@ -1,13 +1,33 @@
|
|||||||
from django import forms
|
from django import forms
|
||||||
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
|
from netbox.registry import registry
|
||||||
from utilities.forms import BootstrapMixin
|
from utilities.forms import BootstrapMixin
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
|
'DashboardWidgetAddForm',
|
||||||
'DashboardWidgetForm',
|
'DashboardWidgetForm',
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_widget_choices():
|
||||||
|
return registry['widgets'].items()
|
||||||
|
|
||||||
|
|
||||||
class DashboardWidgetForm(BootstrapMixin, forms.Form):
|
class DashboardWidgetForm(BootstrapMixin, forms.Form):
|
||||||
title = forms.CharField(
|
title = forms.CharField(
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class DashboardWidgetAddForm(DashboardWidgetForm):
|
||||||
|
widget_class = forms.ChoiceField(
|
||||||
|
choices=get_widget_choices,
|
||||||
|
widget=forms.Select(
|
||||||
|
attrs={
|
||||||
|
'hx-get': reverse_lazy('extras:dashboardwidget_add'),
|
||||||
|
'hx-target': '#widget_add_form',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
field_order = ('widget_class', 'title')
|
||||||
|
@ -88,6 +88,7 @@ urlpatterns = [
|
|||||||
path('changelog/<int:pk>/', include(get_model_urls('extras', 'objectchange'))),
|
path('changelog/<int:pk>/', include(get_model_urls('extras', 'objectchange'))),
|
||||||
|
|
||||||
# User dashboard
|
# User dashboard
|
||||||
|
path('dashboard/widgets/add/', views.DashboardWidgetAddView.as_view(), name='dashboardwidget_add'),
|
||||||
path('dashboard/widgets/<uuid:id>/configure/', views.DashboardWidgetConfigView.as_view(), name='dashboardwidget_config'),
|
path('dashboard/widgets/<uuid:id>/configure/', views.DashboardWidgetConfigView.as_view(), name='dashboardwidget_config'),
|
||||||
path('dashboard/widgets/<uuid:id>/delete/', views.DashboardWidgetDeleteView.as_view(), name='dashboardwidget_delete'),
|
path('dashboard/widgets/<uuid:id>/delete/', views.DashboardWidgetDeleteView.as_view(), name='dashboardwidget_delete'),
|
||||||
|
|
||||||
|
@ -9,10 +9,11 @@ from django.views.generic import View
|
|||||||
from django_rq.queues import get_connection
|
from django_rq.queues import get_connection
|
||||||
from rq import Worker
|
from rq import Worker
|
||||||
|
|
||||||
from extras.dashboard.forms import DashboardWidgetForm
|
from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm
|
||||||
from extras.dashboard.utils import get_widget_class_and_config
|
from extras.dashboard.utils import get_widget_class_and_config
|
||||||
|
from netbox.registry import registry
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from utilities.forms import ConfirmationForm
|
from utilities.forms import ConfirmationForm, get_field_value
|
||||||
from utilities.htmx import is_htmx
|
from utilities.htmx import is_htmx
|
||||||
from utilities.utils import copy_safe_request, count_related, get_viewname, normalize_querydict, shallow_compare_dict
|
from utilities.utils import copy_safe_request, count_related, get_viewname, normalize_querydict, shallow_compare_dict
|
||||||
from utilities.views import ContentTypePermissionRequiredMixin, register_model_view
|
from utilities.views import ContentTypePermissionRequiredMixin, register_model_view
|
||||||
@ -672,6 +673,57 @@ class JournalEntryBulkDeleteView(generic.BulkDeleteView):
|
|||||||
# Dashboard widgets
|
# Dashboard widgets
|
||||||
#
|
#
|
||||||
|
|
||||||
|
class DashboardWidgetAddView(LoginRequiredMixin, View):
|
||||||
|
template_name = 'extras/dashboard/widget_add.html'
|
||||||
|
|
||||||
|
def get(self, request):
|
||||||
|
initial = request.GET or {
|
||||||
|
'widget_class': 'extras.NoteWidget',
|
||||||
|
}
|
||||||
|
widget_form = DashboardWidgetAddForm(initial=initial)
|
||||||
|
widget_name = get_field_value(widget_form, 'widget_class')
|
||||||
|
widget_class = registry['widgets'][widget_name]
|
||||||
|
config_form = widget_class.ConfigForm(prefix='config')
|
||||||
|
|
||||||
|
if not is_htmx(request):
|
||||||
|
return redirect('home')
|
||||||
|
|
||||||
|
return render(request, self.template_name, {
|
||||||
|
'widget_form': widget_form,
|
||||||
|
'config_form': config_form,
|
||||||
|
})
|
||||||
|
|
||||||
|
def post(self, request):
|
||||||
|
widget_form = DashboardWidgetAddForm(request.POST)
|
||||||
|
|
||||||
|
if widget_form.is_valid():
|
||||||
|
widget_class = registry['widgets'][widget_form.cleaned_data['widget_class']]
|
||||||
|
config_form = widget_class.ConfigForm(request.POST, prefix='config')
|
||||||
|
|
||||||
|
if config_form.is_valid():
|
||||||
|
data = widget_form.cleaned_data
|
||||||
|
class_name = data.pop('widget_class')
|
||||||
|
data['config'] = config_form.cleaned_data
|
||||||
|
widget = widget_class(**data)
|
||||||
|
data['class'] = class_name
|
||||||
|
request.user.config.set(f'dashboard.widgets.{widget.id}', data)
|
||||||
|
request.user.config.get(f'dashboard.layout').append({
|
||||||
|
'h': widget.height,
|
||||||
|
'w': widget.width,
|
||||||
|
'id': str(widget.id),
|
||||||
|
})
|
||||||
|
request.user.config.save()
|
||||||
|
|
||||||
|
response = HttpResponse()
|
||||||
|
response['HX-Redirect'] = reverse('home')
|
||||||
|
return response
|
||||||
|
|
||||||
|
return render(request, self.template_name, {
|
||||||
|
'widget_form': widget_form,
|
||||||
|
'config_form': config_form,
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
class DashboardWidgetConfigView(LoginRequiredMixin, View):
|
class DashboardWidgetConfigView(LoginRequiredMixin, View):
|
||||||
template_name = 'extras/dashboard/widget_config.html'
|
template_name = 'extras/dashboard/widget_config.html'
|
||||||
|
|
||||||
|
19
netbox/templates/extras/dashboard/widget_add.html
Normal file
19
netbox/templates/extras/dashboard/widget_add.html
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{% 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_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>
|
@ -30,6 +30,15 @@
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-end px-2">
|
<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">
|
<button id="save_dashboard" class="btn btn-primary btn-sm">
|
||||||
<i class="mdi mdi-content-save-outline"></i> Save
|
<i class="mdi mdi-content-save-outline"></i> Save
|
||||||
</button>
|
</button>
|
||||||
|
Loading…
Reference in New Issue
Block a user