mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Clean up utility functions
This commit is contained in:
parent
892fce1518
commit
96a8c72b05
@ -1,13 +1,14 @@
|
|||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
|
||||||
from netbox.registry import registry
|
from netbox.registry import registry
|
||||||
from extras.constants import DEFAULT_DASHBOARD
|
from extras.constants import DEFAULT_DASHBOARD
|
||||||
from extras.models import Dashboard
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'get_dashboard',
|
'get_dashboard',
|
||||||
'get_default_dashboard_config',
|
'get_default_dashboard',
|
||||||
'get_widget_class_and_config',
|
'get_widget_class',
|
||||||
'register_widget',
|
'register_widget',
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -23,32 +24,36 @@ def register_widget(cls):
|
|||||||
return cls
|
return cls
|
||||||
|
|
||||||
|
|
||||||
def get_widget_class_and_config(dashboard, id):
|
def get_widget_class(name):
|
||||||
config = dict(dashboard.config[id]) # Copy to avoid mutating userconfig data
|
"""
|
||||||
widget_class = registry['widgets'].get(config.pop('class'))
|
Return a registered DashboardWidget class identified by its name.
|
||||||
return widget_class, config
|
"""
|
||||||
|
try:
|
||||||
|
return registry['widgets'][name]
|
||||||
|
except KeyError:
|
||||||
|
raise ValueError(f"Unregistered widget class: {name}")
|
||||||
|
|
||||||
|
|
||||||
def get_dashboard(user):
|
def get_dashboard(user):
|
||||||
"""
|
"""
|
||||||
Return the dashboard layout for a given User.
|
Return the Dashboard for a given User if one exists, or generate a default dashboard.
|
||||||
"""
|
"""
|
||||||
if not user.is_anonymous and hasattr(user, 'dashboard'):
|
if user.is_anonymous:
|
||||||
dashboard = user.dashboard
|
dashboard = get_default_dashboard()
|
||||||
else:
|
else:
|
||||||
dashboard = get_default_dashboard_config()
|
try:
|
||||||
|
dashboard = user.dashboard
|
||||||
|
except ObjectDoesNotExist:
|
||||||
|
# Create a dashboard for this user
|
||||||
|
dashboard = get_default_dashboard()
|
||||||
|
dashboard.user = user
|
||||||
|
dashboard.save()
|
||||||
|
|
||||||
widgets = []
|
return dashboard
|
||||||
for grid_item in dashboard.layout:
|
|
||||||
widget_class, widget_config = get_widget_class_and_config(dashboard, grid_item['id'])
|
|
||||||
widget = widget_class(id=grid_item['id'], **widget_config)
|
|
||||||
widget.set_layout(grid_item)
|
|
||||||
widgets.append(widget)
|
|
||||||
|
|
||||||
return widgets
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_dashboard_config():
|
def get_default_dashboard():
|
||||||
|
from extras.models import Dashboard
|
||||||
dashboard = Dashboard(
|
dashboard = Dashboard(
|
||||||
layout=[],
|
layout=[],
|
||||||
config={}
|
config={}
|
||||||
|
@ -61,6 +61,14 @@ class DashboardWidget:
|
|||||||
def name(self):
|
def name(self):
|
||||||
return f'{self.__class__.__module__.split(".")[0]}.{self.__class__.__name__}'
|
return f'{self.__class__.__module__.split(".")[0]}.{self.__class__.__name__}'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def form_data(self):
|
||||||
|
return {
|
||||||
|
'title': self.title,
|
||||||
|
'color': self.color,
|
||||||
|
'config': self.config,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@register_widget
|
@register_widget
|
||||||
class NoteWidget(DashboardWidget):
|
class NoteWidget(DashboardWidget):
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
from extras.dashboard.utils import get_widget_class
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'Dashboard',
|
'Dashboard',
|
||||||
)
|
)
|
||||||
@ -18,7 +20,30 @@ class Dashboard(models.Model):
|
|||||||
class Meta:
|
class Meta:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def get_widget(self, id):
|
||||||
|
"""
|
||||||
|
Instantiate and return a widget by its ID
|
||||||
|
"""
|
||||||
|
id = str(id)
|
||||||
|
config = dict(self.config[id]) # Copy to avoid mutating instance data
|
||||||
|
widget_class = get_widget_class(config.pop('class'))
|
||||||
|
return widget_class(id=id, **config)
|
||||||
|
|
||||||
|
def get_layout(self):
|
||||||
|
"""
|
||||||
|
Return the dashboard's configured layout, suitable for rendering with gridstack.js.
|
||||||
|
"""
|
||||||
|
widgets = []
|
||||||
|
for grid_item in self.layout:
|
||||||
|
widget = self.get_widget(grid_item['id'])
|
||||||
|
widget.set_layout(grid_item)
|
||||||
|
widgets.append(widget)
|
||||||
|
return widgets
|
||||||
|
|
||||||
def add_widget(self, widget, x=None, y=None):
|
def add_widget(self, widget, x=None, y=None):
|
||||||
|
"""
|
||||||
|
Add a widget to the dashboard, optionally specifying its X & Y coordinates.
|
||||||
|
"""
|
||||||
id = str(widget.id)
|
id = str(widget.id)
|
||||||
self.config[id] = {
|
self.config[id] = {
|
||||||
'class': widget.name,
|
'class': widget.name,
|
||||||
@ -35,6 +60,10 @@ class Dashboard(models.Model):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def delete_widget(self, id):
|
def delete_widget(self, id):
|
||||||
|
"""
|
||||||
|
Delete a widget from the dashboard.
|
||||||
|
"""
|
||||||
|
id = str(id)
|
||||||
del self.config[id]
|
del self.config[id]
|
||||||
self.layout = [
|
self.layout = [
|
||||||
item for item in self.layout if item['id'] != id
|
item for item in self.layout if item['id'] != id
|
||||||
|
@ -10,7 +10,6 @@ from django_rq.queues import get_connection
|
|||||||
from rq import Worker
|
from rq import Worker
|
||||||
|
|
||||||
from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm
|
from extras.dashboard.forms import DashboardWidgetAddForm, DashboardWidgetForm
|
||||||
from extras.dashboard.utils import get_widget_class_and_config
|
|
||||||
from netbox.registry import registry
|
from netbox.registry import registry
|
||||||
from netbox.views import generic
|
from netbox.views import generic
|
||||||
from utilities.forms import ConfirmationForm, get_field_value
|
from utilities.forms import ConfirmationForm, get_field_value
|
||||||
@ -725,10 +724,9 @@ class DashboardWidgetConfigView(LoginRequiredMixin, View):
|
|||||||
template_name = 'extras/dashboard/widget_config.html'
|
template_name = 'extras/dashboard/widget_config.html'
|
||||||
|
|
||||||
def get(self, request, id):
|
def get(self, request, id):
|
||||||
id = str(id)
|
widget = request.user.dashboard.get_widget(id)
|
||||||
widget_class, config = get_widget_class_and_config(request.user.dashboard, id)
|
widget_form = DashboardWidgetForm(initial=widget.form_data)
|
||||||
widget_form = DashboardWidgetForm(initial=config)
|
config_form = widget.ConfigForm(initial=widget.form_data.get('config'), prefix='config')
|
||||||
config_form = widget_class.ConfigForm(initial=config.get('config'), prefix='config')
|
|
||||||
|
|
||||||
if not is_htmx(request):
|
if not is_htmx(request):
|
||||||
return redirect('home')
|
return redirect('home')
|
||||||
@ -740,15 +738,16 @@ class DashboardWidgetConfigView(LoginRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def post(self, request, id):
|
def post(self, request, id):
|
||||||
id = str(id)
|
widget = request.user.dashboard.get_widget(id)
|
||||||
widget_class, config = get_widget_class_and_config(request.user.dashboard, id)
|
|
||||||
widget_form = DashboardWidgetForm(request.POST)
|
widget_form = DashboardWidgetForm(request.POST)
|
||||||
config_form = widget_class.ConfigForm(request.POST, prefix='config')
|
config_form = widget.ConfigForm(request.POST, prefix='config')
|
||||||
|
|
||||||
if widget_form.is_valid() and config_form.is_valid():
|
if widget_form.is_valid() and config_form.is_valid():
|
||||||
data = widget_form.cleaned_data
|
data = widget_form.cleaned_data
|
||||||
data['config'] = config_form.cleaned_data
|
data['config'] = config_form.cleaned_data
|
||||||
request.user.dashboard.config[id].update(data)
|
print(request.user.dashboard.config)
|
||||||
|
print(data)
|
||||||
|
request.user.dashboard.config[str(id)].update(data)
|
||||||
request.user.dashboard.save()
|
request.user.dashboard.save()
|
||||||
|
|
||||||
response = HttpResponse()
|
response = HttpResponse()
|
||||||
@ -766,15 +765,13 @@ class DashboardWidgetDeleteView(LoginRequiredMixin, View):
|
|||||||
template_name = 'generic/object_delete.html'
|
template_name = 'generic/object_delete.html'
|
||||||
|
|
||||||
def get(self, request, id):
|
def get(self, request, id):
|
||||||
id = str(id)
|
widget = request.user.dashboard.get_widget(id)
|
||||||
widget_class, config = get_widget_class_and_config(request.user.dashboard, id)
|
|
||||||
widget = widget_class(**config)
|
|
||||||
form = ConfirmationForm(initial=request.GET)
|
form = ConfirmationForm(initial=request.GET)
|
||||||
|
|
||||||
# If this is an HTMX request, return only the rendered deletion form as modal content
|
# If this is an HTMX request, return only the rendered deletion form as modal content
|
||||||
if is_htmx(request):
|
if is_htmx(request):
|
||||||
return render(request, 'htmx/delete_form.html', {
|
return render(request, 'htmx/delete_form.html', {
|
||||||
'object_type': widget_class.__name__,
|
'object_type': widget.__class__.__name__,
|
||||||
'object': widget,
|
'object': widget,
|
||||||
'form': form,
|
'form': form,
|
||||||
'form_url': reverse('extras:dashboardwidget_delete', kwargs={'id': id})
|
'form_url': reverse('extras:dashboardwidget_delete', kwargs={'id': id})
|
||||||
@ -785,7 +782,6 @@ class DashboardWidgetDeleteView(LoginRequiredMixin, View):
|
|||||||
})
|
})
|
||||||
|
|
||||||
def post(self, request, id):
|
def post(self, request, id):
|
||||||
id = str(id)
|
|
||||||
form = ConfirmationForm(request.POST)
|
form = ConfirmationForm(request.POST)
|
||||||
|
|
||||||
if form.is_valid():
|
if form.is_valid():
|
||||||
|
@ -32,8 +32,8 @@ class HomeView(View):
|
|||||||
if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
|
if settings.LOGIN_REQUIRED and not request.user.is_authenticated:
|
||||||
return redirect('login')
|
return redirect('login')
|
||||||
|
|
||||||
# Build custom dashboard from user's config
|
# Construct the user's custom dashboard layout
|
||||||
widgets = get_dashboard(request.user)
|
dashboard = get_dashboard(request.user).get_layout()
|
||||||
|
|
||||||
# Check whether a new release is available. (Only for staff/superusers.)
|
# Check whether a new release is available. (Only for staff/superusers.)
|
||||||
new_release = None
|
new_release = None
|
||||||
@ -48,7 +48,7 @@ class HomeView(View):
|
|||||||
}
|
}
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
'widgets': widgets,
|
'dashboard': dashboard,
|
||||||
'new_release': new_release,
|
'new_release': new_release,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
{% block content-wrapper %}
|
{% block content-wrapper %}
|
||||||
{# Render the user's customized dashboard #}
|
{# Render the user's customized dashboard #}
|
||||||
<div class="grid-stack">
|
<div class="grid-stack">
|
||||||
{% for widget in widgets %}
|
{% for widget in dashboard %}
|
||||||
{% include 'extras/dashboard/widget.html' %}
|
{% include 'extras/dashboard/widget.html' %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user