Skip to content

Commit e176c7d

Browse files
committed
#9416: cleanup & widget improvements
1 parent a098c3b commit e176c7d

File tree

10 files changed

+104
-20
lines changed

10 files changed

+104
-20
lines changed

netbox/extras/constants.py

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,19 +19,73 @@
1919

2020
# Dashboard
2121
DEFAULT_DASHBOARD = [
22+
{
23+
'widget': 'extras.ObjectCountsWidget',
24+
'width': 4,
25+
'height': 2,
26+
'title': 'Organization',
27+
'config': {
28+
'models': [
29+
'dcim.site',
30+
'tenancy.tenant',
31+
'tenancy.contact',
32+
]
33+
}
34+
},
2235
{
2336
'widget': 'extras.ObjectCountsWidget',
2437
'width': 4,
2538
'height': 3,
2639
'title': 'IPAM',
2740
'config': {
2841
'models': [
42+
'ipam.vrf',
2943
'ipam.aggregate',
3044
'ipam.prefix',
45+
'ipam.iprange',
3146
'ipam.ipaddress',
47+
'ipam.vlan',
48+
]
49+
}
50+
},
51+
{
52+
'widget': 'extras.NoteWidget',
53+
'width': 4,
54+
'height': 2,
55+
'title': 'Welcome!',
56+
'color': 'green',
57+
'config': {
58+
'content': (
59+
'This is your personal dashboard. Feel free to customize it by rearranging, resizing, or removing '
60+
'widgets. You can also add new widgets using the "add widget" button below. Any changes affect only '
61+
'_your_ dashboard, so feel free to experiment!'
62+
)
63+
}
64+
},
65+
{
66+
'widget': 'extras.ObjectCountsWidget',
67+
'width': 4,
68+
'height': 2,
69+
'title': 'Circuits',
70+
'config': {
71+
'models': [
72+
'circuits.provider',
73+
'circuits.circuit',
74+
'circuits.providernetwork',
3275
]
3376
}
3477
},
78+
{
79+
'widget': 'extras.RSSFeedWidget',
80+
'width': 4,
81+
'height': 4,
82+
'title': 'NetBox News',
83+
'config': {
84+
'feed_url': 'http://netbox.dev/rss/',
85+
'max_entries': 10,
86+
'cache_timeout': 14400,
87+
}
88+
},
3589
{
3690
'widget': 'extras.ObjectCountsWidget',
3791
'width': 4,
@@ -41,25 +95,33 @@
4195
'models': [
4296
'dcim.site',
4397
'dcim.rack',
98+
'dcim.devicetype',
4499
'dcim.device',
45-
]
100+
'dcim.cable',
101+
],
46102
}
47103
},
48104
{
49-
'widget': 'extras.NoteWidget',
105+
'widget': 'extras.ObjectCountsWidget',
50106
'width': 4,
51-
'height': 3,
107+
'height': 2,
108+
'title': 'Virtualization',
52109
'config': {
53-
'content': 'Welcome to **NetBox**!'
110+
'models': [
111+
'virtualization.cluster',
112+
'virtualization.virtualmachine',
113+
]
54114
}
55115
},
56116
{
57117
'widget': 'extras.ObjectListWidget',
58118
'width': 12,
59-
'height': 6,
119+
'height': 5,
60120
'title': 'Change Log',
121+
'color': 'blue',
61122
'config': {
62123
'model': 'extras.objectchange',
124+
'page_size': 25,
63125
}
64126
},
65127
]

netbox/extras/dashboard/forms.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from django import forms
22
from django.urls import reverse_lazy
3+
from django.utils.translation import gettext as _
34

45
from netbox.registry import registry
56
from utilities.forms import BootstrapMixin, add_blank_choice
@@ -33,6 +34,7 @@ class DashboardWidgetAddForm(DashboardWidgetForm):
3334
'hx-get': reverse_lazy('extras:dashboardwidget_add'),
3435
'hx-target': '#widget_add_form',
3536
}
36-
)
37+
),
38+
label=_('Widget type')
3739
)
3840
field_order = ('widget_class', 'title', 'color')

netbox/extras/dashboard/utils.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,7 @@ def get_dashboard(user):
5454

5555
def get_default_dashboard():
5656
from extras.models import Dashboard
57-
dashboard = Dashboard(
58-
layout=[],
59-
config={}
60-
)
57+
dashboard = Dashboard()
6158
for widget in DEFAULT_DASHBOARD:
6259
id = str(uuid.uuid4())
6360
dashboard.layout.append({
@@ -70,6 +67,7 @@ def get_default_dashboard():
7067
dashboard.config[id] = {
7168
'class': widget['widget'],
7269
'title': widget.get('title'),
70+
'color': widget.get('color'),
7371
'config': widget.get('config', {}),
7472
}
7573

netbox/extras/dashboard/widgets.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from django.contrib.contenttypes.models import ContentType
88
from django.core.cache import cache
99
from django.template.loader import render_to_string
10+
from django.urls import NoReverseMatch, reverse
1011
from django.utils.translation import gettext as _
1112

1213
from utilities.forms import BootstrapMixin
@@ -126,14 +127,26 @@ class ConfigForm(BootstrapMixin, forms.Form):
126127
model = forms.ChoiceField(
127128
choices=get_content_type_labels
128129
)
130+
page_size = forms.IntegerField(
131+
required=False,
132+
min_value=1,
133+
max_value=100,
134+
help_text=_('The default number of objects to display')
135+
)
129136

130137
def render(self, request):
131138
app_label, model_name = self.config['model'].split('.')
132139
content_type = ContentType.objects.get_by_natural_key(app_label, model_name)
133140
viewname = get_viewname(content_type.model_class(), action='list')
141+
try:
142+
htmx_url = reverse(viewname)
143+
except NoReverseMatch:
144+
htmx_url = None
134145

135146
return render_to_string(self.template_name, {
136147
'viewname': viewname,
148+
'htmx_url': htmx_url,
149+
'page_size': self.config.get('page_size'),
137150
})
138151

139152

netbox/extras/migrations/0087_dashboard.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ class Migration(migrations.Migration):
1717
name='Dashboard',
1818
fields=[
1919
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False)),
20-
('layout', models.JSONField()),
21-
('config', models.JSONField()),
20+
('layout', models.JSONField(default=list)),
21+
('config', models.JSONField(default=dict)),
2222
('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, related_name='dashboard', to=settings.AUTH_USER_MODEL)),
2323
],
2424
),

netbox/extras/models/dashboard.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,12 @@ class Dashboard(models.Model):
1414
on_delete=models.CASCADE,
1515
related_name='dashboard'
1616
)
17-
layout = models.JSONField()
18-
config = models.JSONField()
17+
layout = models.JSONField(
18+
default=list
19+
)
20+
config = models.JSONField(
21+
default=dict
22+
)
1923

2024
class Meta:
2125
pass

netbox/extras/views.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,7 @@ def get(self, request, id):
727727
config_form = widget.ConfigForm(initial=widget.form_data.get('config'), prefix='config')
728728

729729
return render(request, self.template_name, {
730+
'widget_class': widget.__class__,
730731
'widget_form': widget_form,
731732
'config_form': config_form,
732733
'form_url': reverse('extras:dashboardwidget_config', kwargs={'id': id})

netbox/templates/extras/dashboard/widget_config.html

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,11 @@
33
<form hx-post="{{ form_url }}">
44
{% csrf_token %}
55
<div class="modal-header">
6-
<h5 class="modal-title">Widget Configuration</h5>
6+
<h5 class="modal-title">{{ widget_class }} Configuration</h5>
77
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
88
</div>
99
<div class="modal-body">
10+
<p>{{ widget_class.description }}</p>
1011
{% block form %}
1112
{% render_form widget_form %}
1213
{% render_form config_form %}
Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
<div class="htmx-container"
2-
hx-get="{% url viewname %}"
3-
hx-trigger="load"
4-
></div>
1+
{% if htmx_url %}
2+
<div class="htmx-container" hx-get="{{ htmx_url }}{% if page_size %}?per_page={{ page_size }}{% endif %}" hx-trigger="load"></div>
3+
{% else %}
4+
<div class="text-danger text-center">
5+
<i class="mdi mdi-alert"></i> Unable to load content. Invalid view name: <span class="font-monospace">{{ viewname }}</span>
6+
</div>
7+
{% endif %}

netbox/templates/home.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ <h6 class="alert-heading">
4040
<i class="mdi mdi-plus"></i> Add Widget
4141
</a>
4242
<button id="save_dashboard" class="btn btn-primary btn-sm" data-url="{% url 'extras-api:dashboard' %}">
43-
<i class="mdi mdi-content-save-outline"></i> Save
43+
<i class="mdi mdi-content-save-outline"></i> Save Layout
4444
</button>
4545
</div>
4646
{% endblock content-wrapper %}

0 commit comments

Comments
 (0)