mirror of
https://github.com/netbox-community/netbox.git
synced 2024-05-10 07:54:54 +00:00
Create form for setting table preferences
This commit is contained in:
23
netbox/templates/inc/table_config_form.html
Normal file
23
netbox/templates/inc/table_config_form.html
Normal file
@ -0,0 +1,23 @@
|
||||
{% load form_helpers %}
|
||||
|
||||
<button type="button" class="btn btn-primary btn-xs" data-toggle="modal" data-target="#tableconfig" title="Configure table"><i class="fa fa-cog"></i></button>
|
||||
<div class="modal fade" tabindex="-1" id="tableconfig">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
|
||||
<h4 class="modal-title">Table Configuration</h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form action="?return_url={{ request.path }}" method="post" class="form-horizontal">
|
||||
{% csrf_token %}
|
||||
{% render_form table_config_form %}
|
||||
<div class="text-right">
|
||||
<input type="submit" class="btn btn-primary" name="set" value="Save" />
|
||||
<input type="submit" class="btn btn-danger" name="clear" value="Clear" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -18,6 +18,9 @@
|
||||
<h1>{% block title %}{{ content_type.model_class|meta:"verbose_name_plural"|bettertitle }}{% endblock %}</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-{% if filter_form %}9{% else %}12{% endif %}">
|
||||
{% if table_config_form %}
|
||||
{% include 'inc/table_config_form.html' %}
|
||||
{% endif %}
|
||||
{% with bulk_edit_url=content_type.model_class|url_name:"bulk_edit" bulk_delete_url=content_type.model_class|url_name:"bulk_delete" %}
|
||||
{% if permissions.change or permissions.delete %}
|
||||
<form method="post" class="form form-horizontal">
|
||||
|
@ -137,6 +137,27 @@ def form_from_model(model, fields):
|
||||
return type('FormFromModel', (forms.Form,), form_fields)
|
||||
|
||||
|
||||
def apply_bootstrap_classes(form):
|
||||
"""
|
||||
Apply Bootstrap CSS classes to form elements.
|
||||
"""
|
||||
exempt_widgets = [
|
||||
forms.CheckboxInput,
|
||||
forms.ClearableFileInput,
|
||||
forms.FileInput,
|
||||
forms.RadioSelect
|
||||
]
|
||||
|
||||
for field_name, field in form.fields.items():
|
||||
if field.widget.__class__ not in exempt_widgets:
|
||||
css = field.widget.attrs.get('class', '')
|
||||
field.widget.attrs['class'] = ' '.join([css, 'form-control']).strip()
|
||||
if field.required and not isinstance(field.widget, forms.FileInput):
|
||||
field.widget.attrs['required'] = 'required'
|
||||
if 'placeholder' not in field.widget.attrs:
|
||||
field.widget.attrs['placeholder'] = field.label
|
||||
|
||||
|
||||
#
|
||||
# Widgets
|
||||
#
|
||||
@ -663,19 +684,7 @@ class BootstrapMixin(forms.BaseForm):
|
||||
"""
|
||||
def __init__(self, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
exempt_widgets = [
|
||||
forms.CheckboxInput, forms.ClearableFileInput, forms.FileInput, forms.RadioSelect
|
||||
]
|
||||
|
||||
for field_name, field in self.fields.items():
|
||||
if field.widget.__class__ not in exempt_widgets:
|
||||
css = field.widget.attrs.get('class', '')
|
||||
field.widget.attrs['class'] = ' '.join([css, 'form-control']).strip()
|
||||
if field.required and not isinstance(field.widget, forms.FileInput):
|
||||
field.widget.attrs['required'] = 'required'
|
||||
if 'placeholder' not in field.widget.attrs:
|
||||
field.widget.attrs['placeholder'] = field.label
|
||||
apply_bootstrap_classes(self)
|
||||
|
||||
|
||||
class ReturnURLForm(forms.Form):
|
||||
@ -752,3 +761,23 @@ class ImportForm(BootstrapMixin, forms.Form):
|
||||
raise forms.ValidationError({
|
||||
'data': "Invalid YAML data: {}".format(err)
|
||||
})
|
||||
|
||||
|
||||
class TableConfigForm(forms.Form):
|
||||
"""
|
||||
Form for configuring user's table preferences.
|
||||
"""
|
||||
def __init__(self, table, *args, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
field_name = f"tables.{table.__class__.__name__}.columns"
|
||||
self.fields[field_name] = forms.MultipleChoiceField(
|
||||
choices=table.configurable_columns,
|
||||
initial=table.visible_columns,
|
||||
label='Columns',
|
||||
widget=forms.SelectMultiple(
|
||||
attrs={'size': 10}
|
||||
)
|
||||
)
|
||||
|
||||
apply_bootstrap_classes(self)
|
||||
|
@ -6,6 +6,11 @@ class BaseTable(tables.Table):
|
||||
"""
|
||||
Default table for object lists
|
||||
"""
|
||||
class Meta:
|
||||
attrs = {
|
||||
'class': 'table table-hover table-headings',
|
||||
}
|
||||
|
||||
def __init__(self, *args, columns=None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
@ -29,10 +34,19 @@ class BaseTable(tables.Table):
|
||||
self.base_columns['pk'] = pk
|
||||
self.sequence.insert(0, 'pk')
|
||||
|
||||
class Meta:
|
||||
attrs = {
|
||||
'class': 'table table-hover table-headings',
|
||||
}
|
||||
@property
|
||||
def configurable_columns(self):
|
||||
selected_columns = [
|
||||
(name, self.columns[name].verbose_name) for name in self.sequence if name != 'pk'
|
||||
]
|
||||
available_columns = [
|
||||
(name, column.verbose_name) for name, column in self.columns.items() if name not in self.sequence and name != 'pk'
|
||||
]
|
||||
return selected_columns + available_columns
|
||||
|
||||
@property
|
||||
def visible_columns(self):
|
||||
return [name for name in self.sequence if self.columns[name].visible]
|
||||
|
||||
|
||||
class ToggleColumn(tables.CheckBoxColumn):
|
||||
|
@ -24,7 +24,7 @@ from django_tables2 import RequestConfig
|
||||
from extras.models import CustomField, CustomFieldValue, ExportTemplate
|
||||
from extras.querysets import CustomFieldQueryset
|
||||
from utilities.exceptions import AbortTransaction
|
||||
from utilities.forms import BootstrapMixin, CSVDataField
|
||||
from utilities.forms import BootstrapMixin, CSVDataField, TableConfigForm
|
||||
from utilities.utils import csv_format, prepare_cloned_fields
|
||||
from .error_handlers import handle_protectederror
|
||||
from .forms import ConfirmationForm, ImportForm
|
||||
@ -176,11 +176,16 @@ class ObjectListView(View):
|
||||
}
|
||||
RequestConfig(request, paginate).configure(table)
|
||||
|
||||
table_config_form = TableConfigForm(
|
||||
table=table
|
||||
)
|
||||
|
||||
context = {
|
||||
'content_type': content_type,
|
||||
'table': table,
|
||||
'permissions': permissions,
|
||||
'action_buttons': self.action_buttons,
|
||||
'table_config_form': table_config_form,
|
||||
'filter_form': self.filterset_form(request.GET, label_suffix='') if self.filterset_form else None,
|
||||
}
|
||||
context.update(self.extra_context())
|
||||
|
Reference in New Issue
Block a user