mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-26 09:16:10 -06:00
Add color customization to dashboard widgets
This commit is contained in:
parent
e80428e5a1
commit
e9e0738d5d
@ -2,7 +2,8 @@ from django import forms
|
|||||||
from django.urls import reverse_lazy
|
from django.urls import reverse_lazy
|
||||||
|
|
||||||
from netbox.registry import registry
|
from netbox.registry import registry
|
||||||
from utilities.forms import BootstrapMixin
|
from utilities.forms import BootstrapMixin, add_blank_choice
|
||||||
|
from utilities.choices import ButtonColorChoices
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'DashboardWidgetAddForm',
|
'DashboardWidgetAddForm',
|
||||||
@ -18,6 +19,10 @@ class DashboardWidgetForm(BootstrapMixin, forms.Form):
|
|||||||
title = forms.CharField(
|
title = forms.CharField(
|
||||||
required=False
|
required=False
|
||||||
)
|
)
|
||||||
|
color = forms.ChoiceField(
|
||||||
|
choices=add_blank_choice(ButtonColorChoices),
|
||||||
|
required=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class DashboardWidgetAddForm(DashboardWidgetForm):
|
class DashboardWidgetAddForm(DashboardWidgetForm):
|
||||||
|
@ -3,7 +3,6 @@ import uuid
|
|||||||
from django import forms
|
from django import forms
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
from django.utils.translation import gettext as _
|
from django.utils.translation import gettext as _
|
||||||
|
|
||||||
from utilities.forms import BootstrapMixin
|
from utilities.forms import BootstrapMixin
|
||||||
@ -27,7 +26,7 @@ def get_content_type_labels():
|
|||||||
|
|
||||||
|
|
||||||
class DashboardWidget:
|
class DashboardWidget:
|
||||||
title = None
|
default_title = None
|
||||||
description = None
|
description = None
|
||||||
width = 4
|
width = 4
|
||||||
height = 3
|
height = 3
|
||||||
@ -35,11 +34,11 @@ class DashboardWidget:
|
|||||||
class ConfigForm(forms.Form):
|
class ConfigForm(forms.Form):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __init__(self, id=None, title=None, config=None, width=None, height=None, x=None, y=None):
|
def __init__(self, id=None, title=None, color=None, config=None, width=None, height=None, x=None, y=None):
|
||||||
self.id = id or uuid.uuid4()
|
self.id = id or uuid.uuid4()
|
||||||
self.config = config or {}
|
self.config = config or {}
|
||||||
if title:
|
self.title = title or self.default_title
|
||||||
self.title = title
|
self.color = color
|
||||||
if width:
|
if width:
|
||||||
self.width = width
|
self.width = width
|
||||||
if height:
|
if height:
|
||||||
@ -56,7 +55,7 @@ class DashboardWidget:
|
|||||||
self.y = grid_item.get('y')
|
self.y = grid_item.get('y')
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
raise NotImplementedError("DashboardWidget subclasses must define a render() method.")
|
raise NotImplementedError(f"{self.__class__} must define a render() method.")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
@ -66,11 +65,6 @@ class DashboardWidget:
|
|||||||
@register_widget
|
@register_widget
|
||||||
class NoteWidget(DashboardWidget):
|
class NoteWidget(DashboardWidget):
|
||||||
description = _('Display some arbitrary custom content. Markdown is supported.')
|
description = _('Display some arbitrary custom content. Markdown is supported.')
|
||||||
default_content = """
|
|
||||||
<div class="d-flex justify-content-center align-items-center" style="height: 100%">
|
|
||||||
<div class="text-center text-muted">Empty</div>
|
|
||||||
</div>
|
|
||||||
"""
|
|
||||||
|
|
||||||
class ConfigForm(BootstrapMixin, forms.Form):
|
class ConfigForm(BootstrapMixin, forms.Form):
|
||||||
content = forms.CharField(
|
content = forms.CharField(
|
||||||
@ -78,14 +72,12 @@ class NoteWidget(DashboardWidget):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
if content := self.config.get('content'):
|
return render_markdown(self.config.get('content'))
|
||||||
return render_markdown(content)
|
|
||||||
return mark_safe(self.default_content)
|
|
||||||
|
|
||||||
|
|
||||||
@register_widget
|
@register_widget
|
||||||
class ObjectCountsWidget(DashboardWidget):
|
class ObjectCountsWidget(DashboardWidget):
|
||||||
title = _('Objects')
|
default_title = _('Objects')
|
||||||
description = _('Display a set of NetBox models and the number of objects created for each type.')
|
description = _('Display a set of NetBox models and the number of objects created for each type.')
|
||||||
template_name = 'extras/dashboard/widgets/objectcounts.html'
|
template_name = 'extras/dashboard/widgets/objectcounts.html'
|
||||||
|
|
||||||
@ -109,10 +101,11 @@ class ObjectCountsWidget(DashboardWidget):
|
|||||||
|
|
||||||
@register_widget
|
@register_widget
|
||||||
class ChangeLogWidget(DashboardWidget):
|
class ChangeLogWidget(DashboardWidget):
|
||||||
title = _('Change Log')
|
default_title = _('Change Log')
|
||||||
|
description = _('Display the most recent records from the global change log.')
|
||||||
|
template_name = 'extras/dashboard/widgets/changelog.html'
|
||||||
width = 12
|
width = 12
|
||||||
height = 4
|
height = 4
|
||||||
template_name = 'extras/dashboard/widgets/changelog.html'
|
|
||||||
|
|
||||||
def render(self, request):
|
def render(self, request):
|
||||||
return render_to_string(self.template_name, {})
|
return render_to_string(self.template_name, {})
|
||||||
|
@ -689,6 +689,7 @@ class DashboardWidgetAddView(LoginRequiredMixin, View):
|
|||||||
return redirect('home')
|
return redirect('home')
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
|
'widget_class': widget_class,
|
||||||
'widget_form': widget_form,
|
'widget_form': widget_form,
|
||||||
'config_form': config_form,
|
'config_form': config_form,
|
||||||
})
|
})
|
||||||
@ -719,6 +720,7 @@ class DashboardWidgetAddView(LoginRequiredMixin, View):
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
return render(request, self.template_name, {
|
return render(request, self.template_name, {
|
||||||
|
'widget_class': widget_class,
|
||||||
'widget_form': widget_form,
|
'widget_form': widget_form,
|
||||||
'config_form': config_form,
|
'config_form': config_form,
|
||||||
})
|
})
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
gs-id="{{ widget.id }}"
|
gs-id="{{ widget.id }}"
|
||||||
>
|
>
|
||||||
<div class="card grid-stack-item-content">
|
<div class="card grid-stack-item-content">
|
||||||
<div class="card-header text-center text-light bg-secondary p-1">
|
<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">
|
<div class="float-start ps-1">
|
||||||
<a href="#"
|
<a href="#"
|
||||||
hx-get="{% url 'extras:dashboardwidget_config' id=widget.id %}"
|
hx-get="{% url 'extras:dashboardwidget_config' id=widget.id %}"
|
||||||
|
@ -7,7 +7,15 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
{% block form %}
|
{% block form %}
|
||||||
{% render_form widget_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 %}
|
{% render_form config_form %}
|
||||||
{% endblock form %}
|
{% endblock form %}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user