mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Replace ButtonsColumn with ActionsColumn
This commit is contained in:
@ -7,7 +7,7 @@ from dcim.models import (
|
|||||||
)
|
)
|
||||||
from tenancy.tables import TenantColumn
|
from tenancy.tables import TenantColumn
|
||||||
from utilities.tables import (
|
from utilities.tables import (
|
||||||
ActionsColumn, BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn,
|
ActionsColumn, BaseTable, BooleanColumn, ChoiceFieldColumn, ColorColumn, ColoredLabelColumn, LinkedCountColumn,
|
||||||
MarkdownColumn, TagColumn, TemplateColumn, ToggleColumn,
|
MarkdownColumn, TagColumn, TemplateColumn, ToggleColumn,
|
||||||
)
|
)
|
||||||
from .template_code import *
|
from .template_code import *
|
||||||
@ -322,10 +322,8 @@ class DeviceConsolePortTable(ConsolePortTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=ConsolePort,
|
extra_buttons=CONSOLEPORT_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=CONSOLEPORT_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -367,10 +365,8 @@ class DeviceConsoleServerPortTable(ConsoleServerPortTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=ConsoleServerPort,
|
extra_buttons=CONSOLESERVERPORT_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=CONSOLESERVERPORT_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -412,10 +408,8 @@ class DevicePowerPortTable(PowerPortTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=PowerPort,
|
extra_buttons=POWERPORT_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=POWERPORT_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -461,10 +455,8 @@ class DevicePowerOutletTable(PowerOutletTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=PowerOutlet,
|
extra_buttons=POWEROUTLET_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=POWEROUTLET_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -551,10 +543,8 @@ class DeviceInterfaceTable(InterfaceTable):
|
|||||||
linkify=True,
|
linkify=True,
|
||||||
verbose_name='LAG'
|
verbose_name='LAG'
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=Interface,
|
extra_buttons=INTERFACE_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=INTERFACE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -614,10 +604,8 @@ class DeviceFrontPortTable(FrontPortTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=FrontPort,
|
extra_buttons=FRONTPORT_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=FRONTPORT_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -662,10 +650,8 @@ class DeviceRearPortTable(RearPortTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=RearPort,
|
extra_buttons=REARPORT_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=REARPORT_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -713,10 +699,8 @@ class DeviceDeviceBayTable(DeviceBayTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=DeviceBay,
|
extra_buttons=DEVICEBAY_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=DEVICEBAY_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -749,10 +733,8 @@ class ModuleBayTable(DeviceComponentTable):
|
|||||||
|
|
||||||
|
|
||||||
class DeviceModuleBayTable(ModuleBayTable):
|
class DeviceModuleBayTable(ModuleBayTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=DeviceBay,
|
extra_buttons=MODULEBAY_BUTTONS
|
||||||
buttons=('edit', 'delete'),
|
|
||||||
prepend_template=MODULEBAY_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(DeviceComponentTable.Meta):
|
class Meta(DeviceComponentTable.Meta):
|
||||||
@ -803,10 +785,7 @@ class DeviceInventoryItemTable(InventoryItemTable):
|
|||||||
order_by=Accessor('_name'),
|
order_by=Accessor('_name'),
|
||||||
attrs={'td': {'class': 'text-nowrap'}}
|
attrs={'td': {'class': 'text-nowrap'}}
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn()
|
||||||
model=InventoryItem,
|
|
||||||
buttons=('edit', 'delete')
|
|
||||||
)
|
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
model = InventoryItem
|
model = InventoryItem
|
||||||
|
@ -6,8 +6,7 @@ from dcim.models import (
|
|||||||
InventoryItemTemplate, Manufacturer, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate,
|
InventoryItemTemplate, Manufacturer, ModuleBayTemplate, PowerOutletTemplate, PowerPortTemplate, RearPortTemplate,
|
||||||
)
|
)
|
||||||
from utilities.tables import (
|
from utilities.tables import (
|
||||||
ActionsColumn, BaseTable, BooleanColumn, ButtonsColumn, ColorColumn, LinkedCountColumn, MarkdownColumn, TagColumn,
|
ActionsColumn, BaseTable, BooleanColumn, ColorColumn, LinkedCountColumn, MarkdownColumn, TagColumn, ToggleColumn,
|
||||||
ToggleColumn,
|
|
||||||
)
|
)
|
||||||
from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
from .template_code import MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
|
|
||||||
@ -113,10 +112,9 @@ class ComponentTemplateTable(BaseTable):
|
|||||||
|
|
||||||
|
|
||||||
class ConsolePortTemplateTable(ComponentTemplateTable):
|
class ConsolePortTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=ConsolePortTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -126,10 +124,9 @@ class ConsolePortTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
|
|
||||||
class ConsoleServerPortTemplateTable(ComponentTemplateTable):
|
class ConsoleServerPortTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=ConsoleServerPortTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -139,10 +136,9 @@ class ConsoleServerPortTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
|
|
||||||
class PowerPortTemplateTable(ComponentTemplateTable):
|
class PowerPortTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=PowerPortTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -152,10 +148,9 @@ class PowerPortTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
|
|
||||||
class PowerOutletTemplateTable(ComponentTemplateTable):
|
class PowerOutletTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=PowerOutletTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -168,10 +163,9 @@ class InterfaceTemplateTable(ComponentTemplateTable):
|
|||||||
mgmt_only = BooleanColumn(
|
mgmt_only = BooleanColumn(
|
||||||
verbose_name='Management Only'
|
verbose_name='Management Only'
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=InterfaceTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -185,10 +179,9 @@ class FrontPortTemplateTable(ComponentTemplateTable):
|
|||||||
verbose_name='Position'
|
verbose_name='Position'
|
||||||
)
|
)
|
||||||
color = ColorColumn()
|
color = ColorColumn()
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=FrontPortTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -199,10 +192,9 @@ class FrontPortTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
class RearPortTemplateTable(ComponentTemplateTable):
|
class RearPortTemplateTable(ComponentTemplateTable):
|
||||||
color = ColorColumn()
|
color = ColorColumn()
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=RearPortTemplate,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
||||||
prepend_template=MODULAR_COMPONENT_TEMPLATE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -212,9 +204,8 @@ class RearPortTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
|
|
||||||
class ModuleBayTemplateTable(ComponentTemplateTable):
|
class ModuleBayTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=ModuleBayTemplate,
|
sequence=('edit', 'delete')
|
||||||
buttons=('edit', 'delete')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -224,9 +215,8 @@ class ModuleBayTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
|
|
||||||
class DeviceBayTemplateTable(ComponentTemplateTable):
|
class DeviceBayTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=DeviceBayTemplate,
|
sequence=('edit', 'delete')
|
||||||
buttons=('edit', 'delete')
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(ComponentTemplateTable.Meta):
|
class Meta(ComponentTemplateTable.Meta):
|
||||||
@ -236,9 +226,8 @@ class DeviceBayTemplateTable(ComponentTemplateTable):
|
|||||||
|
|
||||||
|
|
||||||
class InventoryItemTemplateTable(ComponentTemplateTable):
|
class InventoryItemTemplateTable(ComponentTemplateTable):
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=InventoryItemTemplate,
|
sequence=('edit', 'delete')
|
||||||
buttons=('edit', 'delete')
|
|
||||||
)
|
)
|
||||||
role = tables.Column(
|
role = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
|
@ -3,9 +3,9 @@ import django_tables2 as tables
|
|||||||
from dcim.models import Location, Region, Site, SiteGroup
|
from dcim.models import Location, Region, Site, SiteGroup
|
||||||
from tenancy.tables import TenantColumn
|
from tenancy.tables import TenantColumn
|
||||||
from utilities.tables import (
|
from utilities.tables import (
|
||||||
BaseTable, ButtonsColumn, ChoiceFieldColumn, LinkedCountColumn, MarkdownColumn, MPTTColumn, TagColumn, ToggleColumn,
|
ActionsColumn, BaseTable, ChoiceFieldColumn, LinkedCountColumn, MarkdownColumn, MPTTColumn, TagColumn, ToggleColumn,
|
||||||
)
|
)
|
||||||
from .template_code import LOCATION_ELEVATIONS
|
from .template_code import LOCATION_BUTTONS
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'LocationTable',
|
'LocationTable',
|
||||||
@ -127,9 +127,8 @@ class LocationTable(BaseTable):
|
|||||||
tags = TagColumn(
|
tags = TagColumn(
|
||||||
url_name='dcim:location_list'
|
url_name='dcim:location_list'
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=Location,
|
extra_buttons=LOCATION_BUTTONS
|
||||||
prepend_template=LOCATION_ELEVATIONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
|
@ -87,7 +87,7 @@ POWERFEED_CABLETERMINATION = """
|
|||||||
<a href="{{ value.get_absolute_url }}">{{ value }}</a>
|
<a href="{{ value.get_absolute_url }}">{{ value }}</a>
|
||||||
"""
|
"""
|
||||||
|
|
||||||
LOCATION_ELEVATIONS = """
|
LOCATION_BUTTONS = """
|
||||||
<a href="{% url 'dcim:rack_elevation_list' %}?site={{ record.site.slug }}&location_id={{ record.pk }}" class="btn btn-sm btn-primary" title="View elevations">
|
<a href="{% url 'dcim:rack_elevation_list' %}?site={{ record.site.slug }}&location_id={{ record.pk }}" class="btn btn-sm btn-primary" title="View elevations">
|
||||||
<i class="mdi mdi-server"></i>
|
<i class="mdi mdi-server"></i>
|
||||||
</a>
|
</a>
|
||||||
@ -99,8 +99,8 @@ LOCATION_ELEVATIONS = """
|
|||||||
|
|
||||||
MODULAR_COMPONENT_TEMPLATE_BUTTONS = """
|
MODULAR_COMPONENT_TEMPLATE_BUTTONS = """
|
||||||
{% load helpers %}
|
{% load helpers %}
|
||||||
{% if perms.dcim.add_invnetoryitemtemplate %}
|
{% if perms.dcim.add_inventoryitemtemplate %}
|
||||||
<a href="{% url 'dcim:inventoryitemtemplate_add' %}?device_type={{ record.device_type.pk }}&component_type={{ record|content_type_id }}&component_id={{ record.pk }}&return_url={{ request.path }}" title="Add inventory item" class="btn btn-primary btn-sm">
|
<a href="{% url 'dcim:inventoryitemtemplate_add' %}?device_type={{ record.device_type_id }}&component_type={{ record|content_type_id }}&component_id={{ record.pk }}&return_url={{ request.path }}" title="Add inventory item" class="btn btn-primary btn-sm">
|
||||||
<i class="mdi mdi-plus-thick" aria-hidden="true"></i>
|
<i class="mdi mdi-plus-thick" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -5,8 +5,8 @@ from django_tables2.utils import Accessor
|
|||||||
from dcim.models import Interface
|
from dcim.models import Interface
|
||||||
from tenancy.tables import TenantColumn
|
from tenancy.tables import TenantColumn
|
||||||
from utilities.tables import (
|
from utilities.tables import (
|
||||||
ActionsColumn, BaseTable, BooleanColumn, ButtonsColumn, ChoiceFieldColumn, ContentTypeColumn, LinkedCountColumn,
|
ActionsColumn, BaseTable, BooleanColumn, ChoiceFieldColumn, ContentTypeColumn, LinkedCountColumn, TagColumn,
|
||||||
TagColumn, TemplateColumn, ToggleColumn,
|
TemplateColumn, ToggleColumn,
|
||||||
)
|
)
|
||||||
from virtualization.models import VMInterface
|
from virtualization.models import VMInterface
|
||||||
from ipam.models import *
|
from ipam.models import *
|
||||||
@ -38,7 +38,7 @@ VLAN_PREFIXES = """
|
|||||||
{% endfor %}
|
{% endfor %}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
VLANGROUP_ADD_VLAN = """
|
VLANGROUP_BUTTONS = """
|
||||||
{% with next_vid=record.get_next_available_vid %}
|
{% with next_vid=record.get_next_available_vid %}
|
||||||
{% if next_vid and perms.ipam.add_vlan %}
|
{% if next_vid and perms.ipam.add_vlan %}
|
||||||
<a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-sm btn-success">
|
<a href="{% url 'ipam:vlan_add' %}?group={{ record.pk }}&vid={{ next_vid }}" title="Add VLAN" class="btn btn-sm btn-success">
|
||||||
@ -77,9 +77,8 @@ class VLANGroupTable(BaseTable):
|
|||||||
tags = TagColumn(
|
tags = TagColumn(
|
||||||
url_name='ipam:vlangroup_list'
|
url_name='ipam:vlangroup_list'
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=VLANGroup,
|
extra_buttons=VLANGROUP_BUTTONS
|
||||||
prepend_template=VLANGROUP_ADD_VLAN
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
from collections import namedtuple
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
import django_tables2 as tables
|
import django_tables2 as tables
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
|
from django.template import Context, Template
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django_tables2.utils import Accessor
|
from django_tables2.utils import Accessor
|
||||||
@ -14,7 +15,6 @@ from utilities.utils import content_type_identifier, content_type_name
|
|||||||
__all__ = (
|
__all__ = (
|
||||||
'ActionsColumn',
|
'ActionsColumn',
|
||||||
'BooleanColumn',
|
'BooleanColumn',
|
||||||
'ButtonsColumn',
|
|
||||||
'ChoiceFieldColumn',
|
'ChoiceFieldColumn',
|
||||||
'ColorColumn',
|
'ColorColumn',
|
||||||
'ColoredLabelColumn',
|
'ColoredLabelColumn',
|
||||||
@ -100,7 +100,14 @@ class ActionsItem:
|
|||||||
|
|
||||||
|
|
||||||
class ActionsColumn(tables.Column):
|
class ActionsColumn(tables.Column):
|
||||||
attrs = {'td': {'class': 'text-end noprint'}}
|
"""
|
||||||
|
A dropdown menu which provides edit, delete, and changelog links for an object. Can optionally include
|
||||||
|
additional buttons rendered from a template string.
|
||||||
|
|
||||||
|
:param sequence: The ordered list of dropdown menu items to include
|
||||||
|
:param extra_buttons: A Django template string which renders additional buttons preceding the actions dropdown
|
||||||
|
"""
|
||||||
|
attrs = {'td': {'class': 'text-end text-nowrap noprint'}}
|
||||||
empty_values = ()
|
empty_values = ()
|
||||||
actions = {
|
actions = {
|
||||||
'edit': ActionsItem('Edit', 'pencil', 'change'),
|
'edit': ActionsItem('Edit', 'pencil', 'change'),
|
||||||
@ -108,12 +115,10 @@ class ActionsColumn(tables.Column):
|
|||||||
'changelog': ActionsItem('Changelog', 'history'),
|
'changelog': ActionsItem('Changelog', 'history'),
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, *args, extra_actions=None, sequence=('edit', 'delete', 'changelog'), **kwargs):
|
def __init__(self, *args, sequence=('edit', 'delete', 'changelog'), extra_buttons='', **kwargs):
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
# Add/update any extra actions passed
|
self.extra_buttons = extra_buttons
|
||||||
if extra_actions:
|
|
||||||
self.actions.update(extra_actions)
|
|
||||||
|
|
||||||
# Determine which actions to enable
|
# Determine which actions to enable
|
||||||
self.actions = {
|
self.actions = {
|
||||||
@ -134,9 +139,10 @@ class ActionsColumn(tables.Column):
|
|||||||
url_appendix = f'?return_url={request.path}' if request else ''
|
url_appendix = f'?return_url={request.path}' if request else ''
|
||||||
|
|
||||||
links = []
|
links = []
|
||||||
|
user = getattr(request, 'user', AnonymousUser())
|
||||||
for action, attrs in self.actions.items():
|
for action, attrs in self.actions.items():
|
||||||
permission = f'{model._meta.app_label}.{attrs.permission}_{model._meta.model_name}'
|
permission = f'{model._meta.app_label}.{attrs.permission}_{model._meta.model_name}'
|
||||||
if attrs.permission is None or request.user.has_perm(permission):
|
if attrs.permission is None or user.has_perm(permission):
|
||||||
url = reverse(f'{viewname_base}_{action}', kwargs={'pk': record.pk})
|
url = reverse(f'{viewname_base}_{action}', kwargs={'pk': record.pk})
|
||||||
links.append(f'<li><a class="dropdown-item" href="{url}{url_appendix}">'
|
links.append(f'<li><a class="dropdown-item" href="{url}{url_appendix}">'
|
||||||
f'<i class="mdi mdi-{attrs.icon}"></i> {attrs.title}</a></li>')
|
f'<i class="mdi mdi-{attrs.icon}"></i> {attrs.title}</a></li>')
|
||||||
@ -144,68 +150,21 @@ class ActionsColumn(tables.Column):
|
|||||||
if not links:
|
if not links:
|
||||||
return ''
|
return ''
|
||||||
|
|
||||||
menu = f'<div class="dropdown">' \
|
menu = f'<span class="dropdown">' \
|
||||||
f'<a class="btn btn-sm btn-outline-secondary dropdown-toggle" href="#" type="button" data-bs-toggle="dropdown">' \
|
f'<a class="btn btn-sm btn-secondary dropdown-toggle" href="#" type="button" data-bs-toggle="dropdown">' \
|
||||||
f'<i class="mdi mdi-wrench"></i></a>' \
|
f'<i class="mdi mdi-wrench"></i></a>' \
|
||||||
f'<ul class="dropdown-menu">{"".join(links)}</ul></div>'
|
f'<ul class="dropdown-menu">{"".join(links)}</ul></span>'
|
||||||
|
|
||||||
|
# Render any extra buttons from template code
|
||||||
|
if self.extra_buttons:
|
||||||
|
template = Template(self.extra_buttons)
|
||||||
|
context = getattr(table, "context", Context())
|
||||||
|
context.update({'record': record})
|
||||||
|
menu = template.render(context) + menu
|
||||||
|
|
||||||
return mark_safe(menu)
|
return mark_safe(menu)
|
||||||
|
|
||||||
|
|
||||||
class ButtonsColumn(tables.TemplateColumn):
|
|
||||||
"""
|
|
||||||
Render edit, delete, and changelog buttons for an object.
|
|
||||||
|
|
||||||
:param model: Model class to use for calculating URL view names
|
|
||||||
:param prepend_content: Additional template content to render in the column (optional)
|
|
||||||
"""
|
|
||||||
buttons = ('changelog', 'edit', 'delete')
|
|
||||||
attrs = {'td': {'class': 'text-end text-nowrap noprint'}}
|
|
||||||
# Note that braces are escaped to allow for string formatting prior to template rendering
|
|
||||||
template_code = """
|
|
||||||
{{% if "changelog" in buttons %}}
|
|
||||||
<a href="{{% url '{app_label}:{model_name}_changelog' pk=record.pk %}}" class="btn btn-outline-dark btn-sm" title="Change log">
|
|
||||||
<i class="mdi mdi-history"></i>
|
|
||||||
</a>
|
|
||||||
{{% endif %}}
|
|
||||||
{{% if "edit" in buttons and perms.{app_label}.change_{model_name} %}}
|
|
||||||
<a href="{{% url '{app_label}:{model_name}_edit' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-warning" title="Edit">
|
|
||||||
<i class="mdi mdi-pencil"></i>
|
|
||||||
</a>
|
|
||||||
{{% endif %}}
|
|
||||||
{{% if "delete" in buttons and perms.{app_label}.delete_{model_name} %}}
|
|
||||||
<a href="{{% url '{app_label}:{model_name}_delete' pk=record.pk %}}?return_url={{{{ request.path }}}}" class="btn btn-sm btn-danger" title="Delete">
|
|
||||||
<i class="mdi mdi-trash-can-outline"></i>
|
|
||||||
</a>
|
|
||||||
{{% endif %}}
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, model, *args, buttons=None, prepend_template=None, **kwargs):
|
|
||||||
if prepend_template:
|
|
||||||
prepend_template = prepend_template.replace('{', '{{')
|
|
||||||
prepend_template = prepend_template.replace('}', '}}')
|
|
||||||
self.template_code = prepend_template + self.template_code
|
|
||||||
|
|
||||||
template_code = self.template_code.format(
|
|
||||||
app_label=model._meta.app_label,
|
|
||||||
model_name=model._meta.model_name,
|
|
||||||
buttons=buttons
|
|
||||||
)
|
|
||||||
|
|
||||||
super().__init__(template_code=template_code, *args, **kwargs)
|
|
||||||
|
|
||||||
# Exclude from export by default
|
|
||||||
if 'exclude_from_export' not in kwargs:
|
|
||||||
self.exclude_from_export = True
|
|
||||||
|
|
||||||
self.extra_context.update({
|
|
||||||
'buttons': buttons or self.buttons,
|
|
||||||
})
|
|
||||||
|
|
||||||
def header(self):
|
|
||||||
return ''
|
|
||||||
|
|
||||||
|
|
||||||
class ChoiceFieldColumn(tables.Column):
|
class ChoiceFieldColumn(tables.Column):
|
||||||
"""
|
"""
|
||||||
Render a ChoiceField value inside a <span> indicating a particular CSS class. This is useful for displaying colored
|
Render a ChoiceField value inside a <span> indicating a particular CSS class. This is useful for displaying colored
|
||||||
|
@ -30,7 +30,8 @@ class TagColumnTest(TestCase):
|
|||||||
|
|
||||||
def test_tagcolumn(self):
|
def test_tagcolumn(self):
|
||||||
template = Template('{% load render_table from django_tables2 %}{% render_table table %}')
|
template = Template('{% load render_table from django_tables2 %}{% render_table table %}')
|
||||||
|
table = TagColumnTable(Site.objects.all(), orderable=False)
|
||||||
context = Context({
|
context = Context({
|
||||||
'table': TagColumnTable(Site.objects.all(), orderable=False)
|
'table': table
|
||||||
})
|
})
|
||||||
template.render(context)
|
template.render(context)
|
||||||
|
@ -3,7 +3,7 @@ import django_tables2 as tables
|
|||||||
from dcim.tables.devices import BaseInterfaceTable
|
from dcim.tables.devices import BaseInterfaceTable
|
||||||
from tenancy.tables import TenantColumn
|
from tenancy.tables import TenantColumn
|
||||||
from utilities.tables import (
|
from utilities.tables import (
|
||||||
BaseTable, ButtonsColumn, ChoiceFieldColumn, ColoredLabelColumn, LinkedCountColumn, MarkdownColumn, TagColumn,
|
ActionsColumn, BaseTable, ChoiceFieldColumn, ColoredLabelColumn, LinkedCountColumn, MarkdownColumn, TagColumn,
|
||||||
ToggleColumn,
|
ToggleColumn,
|
||||||
)
|
)
|
||||||
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
|
||||||
@ -183,10 +183,9 @@ class VirtualMachineVMInterfaceTable(VMInterfaceTable):
|
|||||||
bridge = tables.Column(
|
bridge = tables.Column(
|
||||||
linkify=True
|
linkify=True
|
||||||
)
|
)
|
||||||
actions = ButtonsColumn(
|
actions = ActionsColumn(
|
||||||
model=VMInterface,
|
sequence=('edit', 'delete'),
|
||||||
buttons=('edit', 'delete'),
|
extra_buttons=VMINTERFACE_BUTTONS
|
||||||
prepend_template=VMINTERFACE_BUTTONS
|
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta(BaseTable.Meta):
|
class Meta(BaseTable.Meta):
|
||||||
|
Reference in New Issue
Block a user