mirror of
https://github.com/netbox-community/netbox.git
synced 2025-12-14 04:19:36 -06:00
Introduce SimpleLayout
This commit is contained in:
parent
59899d0d9a
commit
d5cec3723e
@ -21,7 +21,8 @@ from ipam.tables import InterfaceVLANTable, VLANTranslationRuleTable
|
||||
from netbox.object_actions import *
|
||||
from netbox.ui import actions, layout
|
||||
from netbox.ui.panels import (
|
||||
CommentsPanel, NestedGroupObjectPanel, ObjectsTablePanel, PluginContentPanel, RelatedObjectsPanel, TemplatePanel,
|
||||
CommentsPanel, NestedGroupObjectPanel, ObjectsTablePanel, OrganizationalObjectPanel, RelatedObjectsPanel,
|
||||
TemplatePanel,
|
||||
)
|
||||
from netbox.views import generic
|
||||
from utilities.forms import ConfirmationForm
|
||||
@ -228,33 +229,26 @@ class RegionListView(generic.ObjectListView):
|
||||
@register_model_view(Region)
|
||||
class RegionView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = Region.objects.all()
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
NestedGroupObjectPanel(),
|
||||
TagsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
NestedGroupObjectPanel(),
|
||||
TagsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Region',
|
||||
title=_('Child Regions'),
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Region', url_params={'parent': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
layout.Column(
|
||||
RelatedObjectsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Region',
|
||||
title=_('Child Regions'),
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Region', url_params={'parent': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -367,33 +361,26 @@ class SiteGroupListView(generic.ObjectListView):
|
||||
@register_model_view(SiteGroup)
|
||||
class SiteGroupView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = SiteGroup.objects.all()
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
NestedGroupObjectPanel(),
|
||||
TagsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
NestedGroupObjectPanel(),
|
||||
TagsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
model='dcim.SiteGroup',
|
||||
title=_('Child Groups'),
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Region', url_params={'parent': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
layout.Column(
|
||||
RelatedObjectsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
ObjectsTablePanel(
|
||||
model='dcim.SiteGroup',
|
||||
title=_('Child Groups'),
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Region', url_params={'parent': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -524,45 +511,38 @@ class SiteListView(generic.ObjectListView):
|
||||
@register_model_view(Site)
|
||||
class SiteView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = Site.objects.prefetch_related('tenant__group')
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
panels.SitePanel(),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.SitePanel(),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Location',
|
||||
filters={'site_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Location', url_params={'site': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
layout.Column(
|
||||
RelatedObjectsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Device',
|
||||
title=_('Non-Racked Devices'),
|
||||
filters={
|
||||
'site_id': lambda ctx: ctx['object'].pk,
|
||||
'rack_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
'parent_bay_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Device', url_params={'site': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Location',
|
||||
filters={'site_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Location', url_params={'site': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Device',
|
||||
title=_('Non-Racked Devices'),
|
||||
filters={
|
||||
'site_id': lambda ctx: ctx['object'].pk,
|
||||
'rack_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
'parent_bay_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
},
|
||||
actions=[
|
||||
actions.AddObject('dcim.Device', url_params={'site': lambda ctx: ctx['object'].pk}),
|
||||
],
|
||||
),
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -664,58 +644,51 @@ class LocationListView(generic.ObjectListView):
|
||||
@register_model_view(Location)
|
||||
class LocationView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = Location.objects.all()
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
panels.LocationPanel(),
|
||||
TagsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.LocationPanel(),
|
||||
TagsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
],
|
||||
bottom_panels=[
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Location',
|
||||
title=_('Child Locations'),
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject(
|
||||
'dcim.Location',
|
||||
url_params={
|
||||
'site': lambda ctx: ctx['object'].site_id,
|
||||
'parent': lambda ctx: ctx['object'].pk,
|
||||
}
|
||||
),
|
||||
],
|
||||
),
|
||||
layout.Column(
|
||||
RelatedObjectsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Device',
|
||||
title=_('Non-Racked Devices'),
|
||||
filters={
|
||||
'location_id': lambda ctx: ctx['object'].pk,
|
||||
'rack_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
'parent_bay_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
},
|
||||
actions=[
|
||||
actions.AddObject(
|
||||
'dcim.Device',
|
||||
url_params={
|
||||
'site': lambda ctx: ctx['object'].site_id,
|
||||
'parent': lambda ctx: ctx['object'].pk,
|
||||
}
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Location',
|
||||
title=_('Child Locations'),
|
||||
filters={'parent_id': lambda ctx: ctx['object'].pk},
|
||||
actions=[
|
||||
actions.AddObject(
|
||||
'dcim.Location',
|
||||
url_params={
|
||||
'site': lambda ctx: ctx['object'].site_id,
|
||||
'parent': lambda ctx: ctx['object'].pk,
|
||||
}
|
||||
),
|
||||
],
|
||||
),
|
||||
ObjectsTablePanel(
|
||||
model='dcim.Device',
|
||||
title=_('Non-Racked Devices'),
|
||||
filters={
|
||||
'location_id': lambda ctx: ctx['object'].pk,
|
||||
'rack_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
'parent_bay_id': settings.FILTERS_NULL_CHOICE_VALUE,
|
||||
},
|
||||
actions=[
|
||||
actions.AddObject(
|
||||
'dcim.Device',
|
||||
url_params={
|
||||
'site': lambda ctx: ctx['object'].site_id,
|
||||
'parent': lambda ctx: ctx['object'].pk,
|
||||
}
|
||||
),
|
||||
],
|
||||
),
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -817,24 +790,15 @@ class RackRoleListView(generic.ObjectListView):
|
||||
@register_model_view(RackRole)
|
||||
class RackRoleView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = RackRole.objects.all()
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
panels.RackRolePanel(),
|
||||
TagsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
layout.Column(
|
||||
RelatedObjectsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.RackRolePanel(),
|
||||
TagsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
RelatedObjectsPanel(),
|
||||
CustomFieldsPanel(),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -903,28 +867,19 @@ class RackTypeListView(generic.ObjectListView):
|
||||
@register_model_view(RackType)
|
||||
class RackTypeView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = RackType.objects.all()
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
panels.RackTypePanel(),
|
||||
panels.RackDimensionsPanel(title=_('Dimensions')),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
layout.Column(
|
||||
panels.RackNumberingPanel(title=_('Numbering')),
|
||||
panels.RackWeightPanel(title=_('Weight'), exclude=['total_weight']),
|
||||
CustomFieldsPanel(),
|
||||
RelatedObjectsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.RackTypePanel(),
|
||||
panels.RackDimensionsPanel(title=_('Dimensions')),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
panels.RackNumberingPanel(title=_('Numbering')),
|
||||
panels.RackWeightPanel(title=_('Weight'), exclude=['total_weight']),
|
||||
CustomFieldsPanel(),
|
||||
RelatedObjectsPanel(),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -1043,30 +998,21 @@ class RackElevationListView(generic.ObjectListView):
|
||||
@register_model_view(Rack)
|
||||
class RackView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = Rack.objects.prefetch_related('site__region', 'tenant__group', 'location', 'role')
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
panels.RackPanel(),
|
||||
panels.RackDimensionsPanel(title=_('Dimensions')),
|
||||
panels.RackNumberingPanel(title=_('Numbering')),
|
||||
panels.RackWeightPanel(title=_('Weight')),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
layout.Column(
|
||||
TemplatePanel('dcim/panels/rack_elevations.html'),
|
||||
RelatedObjectsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.RackPanel(),
|
||||
panels.RackDimensionsPanel(title=_('Dimensions')),
|
||||
panels.RackNumberingPanel(title=_('Numbering')),
|
||||
panels.RackWeightPanel(title=_('Weight')),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
TemplatePanel('dcim/panels/rack_elevations.html'),
|
||||
RelatedObjectsPanel(),
|
||||
],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
@ -1199,27 +1145,18 @@ class RackReservationListView(generic.ObjectListView):
|
||||
@register_model_view(RackReservation)
|
||||
class RackReservationView(generic.ObjectView):
|
||||
queryset = RackReservation.objects.all()
|
||||
layout = layout.Layout(
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
panels.RackPanel(title=_('Rack'), accessor='rack', only=['region', 'site', 'location']),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
PluginContentPanel('left_page'),
|
||||
),
|
||||
layout.Column(
|
||||
TemplatePanel('dcim/panels/rack_elevations.html'),
|
||||
RelatedObjectsPanel(),
|
||||
PluginContentPanel('right_page'),
|
||||
),
|
||||
),
|
||||
layout.Row(
|
||||
layout.Column(
|
||||
PluginContentPanel('full_width_page'),
|
||||
),
|
||||
),
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[
|
||||
panels.RackPanel(accessor='rack', only=['region', 'site', 'location']),
|
||||
CustomFieldsPanel(),
|
||||
TagsPanel(),
|
||||
CommentsPanel(),
|
||||
ImageAttachmentsPanel(),
|
||||
],
|
||||
right_panels=[
|
||||
TemplatePanel('dcim/panels/rack_elevations.html'),
|
||||
RelatedObjectsPanel(),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@ -1294,6 +1231,10 @@ class ManufacturerListView(generic.ObjectListView):
|
||||
@register_model_view(Manufacturer)
|
||||
class ManufacturerView(GetRelatedModelsMixin, generic.ObjectView):
|
||||
queryset = Manufacturer.objects.all()
|
||||
layout = layout.SimpleLayout(
|
||||
left_panels=[OrganizationalObjectPanel(), TagsPanel()],
|
||||
right_panels=[RelatedObjectsPanel(), CustomFieldsPanel()],
|
||||
)
|
||||
|
||||
def get_extra_context(self, request, instance):
|
||||
return {
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
from netbox.ui.panels import Panel
|
||||
from netbox.ui.panels import Panel, PluginContentPanel
|
||||
|
||||
__all__ = (
|
||||
'Column',
|
||||
'Layout',
|
||||
'Row',
|
||||
'SimpleLayout',
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Base classes
|
||||
#
|
||||
|
||||
class Layout:
|
||||
|
||||
def __init__(self, *rows):
|
||||
@ -32,3 +37,27 @@ class Column:
|
||||
if not isinstance(panel, Panel):
|
||||
raise TypeError(f"Panel {i} must be an instance of a Panel, not {type(panel)}.")
|
||||
self.panels = panels
|
||||
|
||||
|
||||
#
|
||||
# Standard layouts
|
||||
#
|
||||
|
||||
class SimpleLayout(Layout):
|
||||
"""
|
||||
A layout with one row of two columns and a second row with one column. Includes registered plugin content.
|
||||
"""
|
||||
def __init__(self, left_panels=None, right_panels=None, bottom_panels=None):
|
||||
left_panels = left_panels or []
|
||||
right_panels = right_panels or []
|
||||
bottom_panels = bottom_panels or []
|
||||
rows = [
|
||||
Row(
|
||||
Column(*left_panels, PluginContentPanel('left_page')),
|
||||
Column(*right_panels, PluginContentPanel('right_page')),
|
||||
),
|
||||
Row(
|
||||
Column(*bottom_panels, PluginContentPanel('full_width_page'))
|
||||
)
|
||||
]
|
||||
super().__init__(*rows)
|
||||
|
||||
@ -149,6 +149,7 @@ class ObjectPanel(Panel, metaclass=ObjectPanelMeta):
|
||||
|
||||
return {
|
||||
**super().get_context(context),
|
||||
'title': self.title or title(obj._meta.verbose_name),
|
||||
'attrs': [
|
||||
{
|
||||
'label': attr.label or title(name),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user