--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/pyams_skin/table.py Thu Feb 19 10:59:00 2015 +0100
@@ -0,0 +1,154 @@
+#
+# Copyright (c) 2008-2015 Thierry Florac <tflorac AT ulthar.net>
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+
+__docformat__ = 'restructuredtext'
+
+# import standard library
+
+# import interfaces
+from pyams_skin.interfaces.container import ITable, ITableElementEditor
+from pyams_skin.layer import IPyAMSLayer
+from z3c.table.interfaces import IColumn
+from zope.container.interfaces import IContained
+
+# import packages
+from pyams_template.template import get_view_template, template_config
+from pyams_utils.adapter import ContextRequestViewAdapter, adapter_config
+from pyams_utils.url import absolute_url
+from pyramid.url import resource_url
+from z3c.table.column import Column, GetAttrColumn
+from z3c.table.table import Table
+from zope.interface import implementer, Interface
+
+from pyams_skin import _
+
+
+@adapter_config(context=(IContained, IPyAMSLayer, ITable), provides=ITableElementEditor)
+class DefaultElementEditorAdapter(ContextRequestViewAdapter):
+ """Default contained element editor"""
+
+ view_name = 'properties.html'
+
+ @property
+ def url(self):
+ return resource_url(self.context, self.request, self.view_name)
+
+ modal_target = True
+
+
+def get_element_editor(table, element):
+ """Get editor for selected element"""
+ registry = table.request.registry
+ return registry.queryMultiAdapter((element, table.request, table), ITableElementEditor)
+
+
+@template_config(template='templates/table.pt', layer=IPyAMSLayer)
+@implementer(ITable)
+class BaseTable(Table):
+ """Custom table"""
+
+ id = _("TableID")
+ title = _("Container elements")
+
+ cssClasses = {'table': 'table table-bordered table-striped table-hover table-tight datatable'}
+
+ @property
+ def data_attributes(self):
+ return {'tr': {'id': lambda x: '{0}::{1}'.format(self.id, x.__name__),
+ 'data-ams-element-name': lambda x: x.__name__,
+ 'data-ams-url': lambda x: getattr(get_element_editor(self, x), 'url', ''),
+ 'data-toggle': lambda x: 'modal' if getattr(get_element_editor(self, x), 'modal_target', None) else None}}
+
+ batchSize = 10000
+ startBatchingAt = 10000
+
+ def getBatchSize(self):
+ return int(self.request.params.get(self.prefix + '-batchSize', self.batchSize))
+
+ def getBatchStart(self):
+ return int(self.request.params.get(self.prefix + '-batchStart', self.batchStart))
+
+ def getSortOn(self):
+ return self.request.params.get(self.prefix + '-sortOn', self.sortOn)
+
+ def getSortOrder(self):
+ return self.request.params.get(self.prefix + '-sortOrder', self.sortOrder)
+
+ @staticmethod
+ def check_data_attribute(attribute, source):
+ if isinstance(attribute, str):
+ return attribute
+ elif callable(attribute):
+ return attribute(source)
+ else:
+ return str(attribute)
+
+ def get_data_attributes(self, element, source, column=None):
+ attrs = self.data_attributes.get(element)
+ if attrs:
+ result = ''
+ for key, value in attrs.items():
+ checked_value = self.check_data_attribute(value, source)
+ if checked_value is not None:
+ result += "{0}='{1}'".format(key, checked_value)
+ return result
+ else:
+ return ''
+
+ render = get_view_template()
+
+ def renderTable(self):
+ return super(BaseTable, self).renderTable() \
+ .replace('<table', '<table %s' % self.get_data_attributes('table', self))
+
+ def renderRow(self, row, cssClass=None):
+ return super(BaseTable, self).renderRow(row, cssClass) \
+ .replace('<tr', '<tr %s' % self.get_data_attributes('tr', row[0][0]))
+
+ def renderCell(self, item, column, colspan=0):
+ return super(BaseTable, self).renderCell(item, column, colspan) \
+ .replace('<td', '<td %s' % self.get_data_attributes('td', item, column))
+
+
+@adapter_config(name='name', context=(Interface, IPyAMSLayer, BaseTable), provides=IColumn)
+class NameColumn(GetAttrColumn):
+ """Container column"""
+
+ header = _("Name")
+ attrName = '__name__'
+
+
+class ActionColumn(Column):
+ """Base action icon column"""
+
+ header = ''
+ icon_class = 'fa fa-fw fa-search'
+ icon_hint = _("Search")
+ cssClasses = {'th': 'action',
+ 'td': 'action'}
+ url = "#"
+ target = '#content'
+ modal_target = False
+
+ def renderCell(self, item):
+ translate = self.request.localizer.translate
+ return '''<a class="hint" title="{title}" href="{url}"
+ data-ams-target="{target}" {modal} data-ams-hint-gravity="se">
+ <i class="{icon_class}"></i>
+ </a>'''.format(title=translate(self.icon_hint),
+ url=self.get_url(item),
+ target=self.target,
+ modal='data-toggle="modal"' if self.modal_target else '',
+ icon_class=self.icon_class)
+
+ def get_url(self, item):
+ return absolute_url(item, self.request, self.url)