Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NDEV-10 Catalog for productivity/management reports to make them faster #157

Merged
merged 6 commits into from
Jul 10, 2017
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 68 additions & 25 deletions bika/lims/browser/bika_listing.py
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ class BikaListingView(BrowserView):

# With this setting, we allow categories to be simple empty place-holders.
# When activated, the category data will be fetched from the server,
# and complted inline. This is useful for list which will have many
# and completed inline. This is useful for lists which will have many
# thousands of entries in many categories, where loading the entire list
# in HTML would be very slow.
ajax_categories = False
Expand Down Expand Up @@ -355,26 +355,69 @@ class BikaListingView(BrowserView):
# all entries without values.
#
# Possible column dictionary keys are:
# - allow_edit
#
# - allow_edit:
# This field is made editable.
# Interim fields are always editable
# - type
# "string" is the default.
# "boolean" a checkbox is rendered
# "date" A text field is rendered, with a jquery DatePicker attached.
# "choices" renders a dropdown. The vocabulary data must be placed in
# item['choices'][column_id]. it's a list of dictionaries:
# [{'ResultValue':x}, {'ResultText',x}].
# - index
# The name of the catalog index for the column. Allows full-table
# sorting.
# - sortable: if False, adds nosort class to this column.
# - toggle: enable/disable column toggle ability.
# - input_class: CSS class applied to input widget in edit mode
# autosave: when js detects this variable as 'true',
# the system will save the value after been
# introduced via ajax.
# - input_width: size attribute applied to input widget in edit mode
#
# - type:
# "string" is the default.
# "boolean" a checkbox is rendered
# "date" A text field is rendered, with a jquery DatePicker attached.
# "choices" Renders a dropdown. The vocabulary data must be placed in
# item['choices'][column_id]. It's a list of dictionaries:
# [{'ResultValue':x}, {'ResultText',x}].
#
# - index:
# The name of the catalog index for the column. Allows full-table
# sorting.
#
# - sortable:
# If False, adds nosort class to this column.
#
# - toggle:
# Enable/disable column toggle ability.
#
# - input_class:
# CSS class applied to input widget in edit mode
# autosave: when js detects this variable as 'true',
# the system will save the value after been
# introduced via ajax.
#
# - input_width:
# Size attribute applied to input widget in edit mode
#
# - attr:
# The name of the catalog column/metadata field from where to retrieve the data
# that will be rendered in the column for a particular object. If not specified
# then the column key will be used as this value. As an example:
#
# self.columns = {
# 'file_size': {
# 'title': _("Size"),
# 'attr': 'getFileSize',
# 'sortable': False, }, }
#
# ^Here, getFileSize will be used to retrieve the data
#
# self.columns = {
# 'file_size': {
# 'title': _("Size"),
# 'sortable': False, }, }
#
# ^Here, file_size will be used to retrieve the data
#
# - title:
# Title that will be used to name the column when rendered
#
# - replace_url:
# if replace_url:
# attrobj = getFromString(obj, replace_url)
# if attrobj:
# results_dict['replace'][key] = \
# '<a href="%s">%s</a>' % (attrobj, value)
#

columns = {
'obj_type': {'title': _('Type')},
'id': {'title': _('ID')},
Expand Down Expand Up @@ -865,17 +908,17 @@ def folderitems(self, full_objects=False, classic=True):
No object is needed by default. We should be able to get all
the listing columns taking advantage of the catalog's metadata,
so that the listing will be much more faster. If a very specific
info has to be retrive from the objects, we can define
info has to be retrieve from the objects, we can define
full_objects as True but performance can be lowered.

:full_objects: a boolean, if True, each dictionary will contain an item
with the cobject itself. item.get('obj') will return a object.
with the object itself. item.get('obj') will return a object.
Only works with the 'classic' way.
WARNING: :full_objects: could create a big performance hit!
:classic: if True, the old way folderitems works will be executed. This
function is mainly used to mantain the integrity with the old version.
function is mainly used to maintain the integrity with the old version.
"""
# Getting a security manager instance for the current reques
# Getting a security manager instance for the current request
self.security_manager = getSecurityManager()
self.workflow = getToolByName(self.context, 'portal_workflow')
if not hasattr(self, 'contentsMethod'):
Expand Down Expand Up @@ -984,7 +1027,7 @@ def folderitems(self, full_objects=False, classic=True):
value = attrobj if attrobj else value

# Custom attribute? Inspect to set the value
# for the current column dinamically
# for the current column dynamically
vattr = self.columns[key].get('attr', None)
if vattr:
attrobj = getFromString(obj, vattr)
Expand Down Expand Up @@ -1018,7 +1061,7 @@ def _fetch_brains(self, idxfrom=0):
# Creating a copy of the contentFilter dictionary in order to include
# the filter bar's filtering additions in the query. We don't want to
# modify contentFilter with those 'extra' filtering elements to be
# inculded in the.
# included in the.
contentFilterTemp = copy.deepcopy(self.contentFilter)
addition = self.get_filter_bar_queryaddition()
# Adding the extra filtering elements
Expand Down
139 changes: 70 additions & 69 deletions bika/lims/browser/reports/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
from bika.lims.interfaces import IProductivityReport
from bika.lims.interfaces import IQualityControlReport
from bika.lims.interfaces import IAdministrationReport
from bika.lims.catalog.report_catalog import CATALOG_REPORT_LISTING
from DateTime import DateTime
from plone.app.layout.globals.interfaces import IViewView
from Products.CMFCore.utils import getToolByName
Expand Down Expand Up @@ -116,14 +117,15 @@ class ReportHistoryView(BikaListingView):
def __init__(self, context, request):
super(ReportHistoryView, self).__init__(context, request)

self.catalog = "bika_catalog"
# this will be reset in the call to filter on own reports
self.contentFilter = {'portal_type': 'Report',
'sort_order': 'reverse'}
self.catalog = CATALOG_REPORT_LISTING

self.context_actions = {}
self.show_sort_column = False
self.show_select_row = False
self.show_select_column = True
self.show_select_column = False
self.show_column_toggles = False
self.show_workflow_action_buttons = False
self.show_select_all_checkbox = False
self.pagesize = 50

self.icon = self.portal_url + "/++resource++bika.lims.images/report_big.png"
Expand All @@ -135,48 +137,45 @@ def __init__(self, context, request):
self.review_states = []

def __call__(self):
self.columns = {
'Title': {
'title': _('Title'),
'attr': 'Title',
'index': 'title', },
'file_size': {
'title': _("Size"),
'attr': 'getFileSize',
'sortable': False, },
'created': {
'title': _("Created"),
'attr': 'created',
'index': 'created', },
'creator': {
'title': _("By"),
'attr': 'getCreatorFullName',
'index': 'Creator', }, }
self.review_states = [
{'id': 'default',
'title': 'All',
'contentFilter': {},
'columns': ['Title',
'file_size',
'created',
'creator']},
]

self.contentFilter = {
'portal_type': 'Report',
'sort_order': 'reverse'}

this_client = logged_in_client(self.context)
if this_client:
self.contentFilter = {
'portal_type': 'Report',
'getClientUID': this_client.UID(),
'sort_order': 'reverse'}
self.columns = {
'Title': {'title': _('Title')},
'FileSize': {'title': _('Size')},
'Created': {'title': _('Created')},
'By': {'title': _('By')}, }
self.review_states = [
{'id': 'default',
'title': 'All',
'contentFilter': {},
'columns': ['Title',
'FileSize',
'Created',
'By']},
]
self.contentFilter['getClientUID'] = this_client.UID()
else:
self.contentFilter = {
'portal_type': 'Report',
'sort_order': 'reverse'}

self.columns = {
'Client': {'title': _('Client')},
'Title': {'title': _('Report Type')},
'FileSize': {'title': _('Size')},
'Created': {'title': _('Created')},
'By': {'title': _('By')},
}
self.review_states = [
{'id': 'default',
'title': 'All',
'contentFilter': {},
'columns': ['Client',
'Title',
'FileSize',
'Created',
'By']},
]
self.columns['client'] = {
'title': _('Client'),
'attr': 'getClientTitle',
'replace_url': 'getClientURL', }

return super(ReportHistoryView, self).__call__()

Expand All @@ -188,32 +187,34 @@ def lookupMime(self, name):
else:
return name

def folderitems(self):
items = BikaListingView.folderitems(self)
props = self.context.portal_properties.site_properties
for x in range(len(items)):
if 'obj' not in items[x]:
continue
obj = items[x]['obj']
obj_url = obj.absolute_url()
file = obj.getReportFile()
icon = file.icon

items[x]['Client'] = ''
client = obj.getClient()
if client:
items[x]['replace']['Client'] = "<a href='%s'>%s</a>" % \
(client.absolute_url(),
client.Title())
items[x]['FileSize'] = '%sKb' % (file.get_size() / 1024)
items[x]['Created'] = self.ulocalized_time(obj.created())
items[x]['By'] = self.user_fullname(obj.Creator())

items[x]['replace']['Title'] = \
"<a href='%s/at_download/ReportFile'>%s</a>" % \
(obj_url, items[x]['Title'])
return items
def folderitem(self, obj, item, index):
item = BikaListingView.folderitem(self, obj, item, index)
# https://github.com/collective/uwosh.pfg.d2c/issues/20
# https://github.com/collective/uwosh.pfg.d2c/pull/21
item['replace']['Title'] = \
"<a href='%s/ReportFile'>%s</a>" % \
(item['url'], item['Title'])
item['replace']['created'] = self.ulocalized_time(item['created'])
return item

def folderitems(self):
return BikaListingView.folderitems(self, classic=False)
# props = self.context.portal_properties.site_properties
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All those commented lines can be deleted

# for x in range(len(items)):
# if 'obj' not in items[x]:
# continue
# obj = items[x]['obj']
# #obj_url = obj.absolute_url()
# #file = obj.getReportFile()
# #icon = file.icon
#
# items[x]['Client'] = ''
# client = obj.getClient()
# if client:
# items[x]['replace']['Client'] = "<a href='%s'>%s</a>" % \
# (client.absolute_url(),
# client.Title())
# return items

class SubmitForm(BrowserView):
""" Redirect to specific report
Expand Down
2 changes: 2 additions & 0 deletions bika/lims/catalog/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@
from .analysis_catalog import CATALOG_ANALYSIS_LISTING
from .autoimportlogs_catalog import CATALOG_AUTOIMPORTLOGS_LISTING
from .worksheet_catalog import CATALOG_WORKSHEET_LISTING
from .report_catalog import CATALOG_REPORT_LISTING
# Catalog classes
from .bika_catalog import BikaCatalog
from .bikasetup_catalog import BikaSetupCatalog
from .analysis_catalog import BikaAnalysisCatalog
from .analysisrequest_catalog import BikaCatalogAnalysisRequestListing
from .autoimportlogs_catalog import BikaCatalogAutoImportLogsListing
from .worksheet_catalog import BikaCatalogWorksheetListing
from .report_catalog import BikaCatalogReport
# Catalog public functions
from .catalog_utilities import getCatalogDefinitions
from .catalog_utilities import setup_catalogs
Expand Down
4 changes: 4 additions & 0 deletions bika/lims/catalog/catalog_utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
bika_catalog_autoimportlogs_listing_definition
from bika.lims.catalog.worksheet_catalog import \
bika_catalog_worksheet_listing_definition
from bika.lims.catalog.report_catalog import \
bika_catalog_report_definition


def getCatalogDefinitions():
Expand All @@ -26,11 +28,13 @@ def getCatalogDefinitions():
analysis = bika_catalog_analysis_listing_definition
autoimportlogs = bika_catalog_autoimportlogs_listing_definition
worksheet = bika_catalog_worksheet_listing_definition
report = bika_catalog_report_definition
# Merging the catalogs
final.update(analysis_request)
final.update(analysis)
final.update(autoimportlogs)
final.update(worksheet)
final.update(report)
return final


Expand Down
Loading