diff --git a/CHANGES.rst b/CHANGES.rst
index 7f16b25ee9..56faadad32 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -4,6 +4,7 @@ Changelog
2.0.0rc3 (unreleased)
---------------------
+- #1727 Cleanup Controlpanel Items
- #1726 Content rules control panel templates styled
- #1724 Purge stale metadata and indexes from analysis catalog
- #1720 Fix UnicodeDecodeError for Instrument Import Log View
diff --git a/src/bika/lims/__init__.py b/src/bika/lims/__init__.py
index 9022d9dbbf..327c9f2c4e 100644
--- a/src/bika/lims/__init__.py
+++ b/src/bika/lims/__init__.py
@@ -94,7 +94,6 @@ def initialize(context):
from bika.lims.content.containertype import ContainerType # noqa
from bika.lims.content.department import Department # noqa
from bika.lims.content.duplicateanalysis import DuplicateAnalysis # noqa
- from bika.lims.content.identifiertype import IdentifierType # noqa
from bika.lims.content.instrument import Instrument # noqa
from bika.lims.content.instrumentcalibration import InstrumentCalibration # noqa
from bika.lims.content.instrumentcertification import InstrumentCertification # noqa
@@ -149,7 +148,6 @@ def initialize(context):
from bika.lims.controlpanel.bika_containers import Containers # noqa
from bika.lims.controlpanel.bika_containertypes import ContainerTypes # noqa
from bika.lims.controlpanel.bika_departments import Departments # noqa
- from bika.lims.controlpanel.bika_identifiertypes import IdentifierTypes # noqa
from bika.lims.controlpanel.bika_instrumentlocations import InstrumentLocations # noqa
from bika.lims.controlpanel.bika_instruments import Instruments # noqa
from bika.lims.controlpanel.bika_instrumenttypes import InstrumentTypes # noqa
diff --git a/src/bika/lims/controlpanel/bika_analysiscategories.py b/src/bika/lims/controlpanel/bika_analysiscategories.py
index 7cffc67b82..b6d1326a52 100644
--- a/src/bika/lims/controlpanel/bika_analysiscategories.py
+++ b/src/bika/lims/controlpanel/bika_analysiscategories.py
@@ -86,8 +86,7 @@ def __init__(self, context, request):
}),
("SortKey", {
"title": _("Sort Key"),
- "attr": "getSortKey",
- "sortable": False
+ "sortable": True
}),
))
@@ -125,6 +124,7 @@ def folderitem(self, obj, item, index):
item["replace"]["Title"] = get_link(url, value=title)
item["Description"] = description
+ item["SortKey"] = obj.getSortKey()
department = obj.getDepartment()
if department:
diff --git a/src/bika/lims/controlpanel/bika_analysisservices.py b/src/bika/lims/controlpanel/bika_analysisservices.py
index ae04f3ffec..e2f2953afc 100644
--- a/src/bika/lims/controlpanel/bika_analysisservices.py
+++ b/src/bika/lims/controlpanel/bika_analysisservices.py
@@ -19,16 +19,7 @@
# Some rights reserved, see README and LICENSE.
import collections
-from senaite.core.interfaces import IHideActionsMenu
-from transaction import savepoint
-from Products.ATContentTypes.content.schemata import finalizeATCTSchema
-from Products.Archetypes import atapi
-from Products.CMFCore.utils import getToolByName
-from Products.CMFPlone.utils import _createObjectByType
-from Products.CMFPlone.utils import safe_unicode
-from Products.Five.browser import BrowserView
-from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -45,6 +36,15 @@
from plone.app.folder.folder import ATFolder
from plone.app.folder.folder import ATFolderSchema
from plone.app.layout.globals.interfaces import IViewView
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content.schemata import finalizeATCTSchema
+from Products.CMFCore.utils import getToolByName
+from Products.CMFPlone.utils import _createObjectByType
+from Products.CMFPlone.utils import safe_unicode
+from Products.Five.browser import BrowserView
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from senaite.core.interfaces import IHideActionsMenu
+from transaction import savepoint
from zope.i18n.locales import locales
from zope.interface.declarations import implements
@@ -249,7 +249,6 @@ def __init__(self, context, request):
"sortable": False}),
("SortKey", {
"title": _("Sort Key"),
- "attr": "getSortKey",
"sortable": False}),
))
@@ -396,6 +395,10 @@ def folderitem(self, obj, item, index):
unit = obj.getUnit()
item["Unit"] = unit and format_supsub(unit) or ""
+ # Sort key
+ sortkey = obj.getSortKey()
+ item["SortKey"] = sortkey
+
# Icons
after_icons = ""
if obj.getAccredited():
diff --git a/src/bika/lims/controlpanel/bika_artemplates.py b/src/bika/lims/controlpanel/bika_artemplates.py
index 948bd4c208..04236a4883 100644
--- a/src/bika/lims/controlpanel/bika_artemplates.py
+++ b/src/bika/lims/controlpanel/bika_artemplates.py
@@ -126,5 +126,6 @@ class ARTemplates(ATFolder):
displayContentsTab = False
schema = schema
+
schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(ARTemplates, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_batchlabels.py b/src/bika/lims/controlpanel/bika_batchlabels.py
index 0657874409..8c099d4b23 100644
--- a/src/bika/lims/controlpanel/bika_batchlabels.py
+++ b/src/bika/lims/controlpanel/bika_batchlabels.py
@@ -18,16 +18,18 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
-from bika.lims import api
+import collections
+
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import IBatchLabels
from bika.lims.permissions import AddBatchLabel
from bika.lims.utils import get_link
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -36,52 +38,72 @@ class BatchLabelsView(BikaListingView):
def __init__(self, context, request):
super(BatchLabelsView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'BatchLabel',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=BatchLabel',
- 'permission': AddBatchLabel,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "BatchLabel",
+ "sort_on": "sortable_title",
+ }
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=BatchLabel",
+ "permission": AddBatchLabel,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.title = self.context.translate(_("Batch Labels"))
- self.icon = self.portal_url + "/++resource++bika.lims.images/batchlabel_big.png"
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/batchlabel_big.png"
+ )
self.description = ""
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Label'),
- 'index':'sortable_title'},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Label"),
+ "index": "sortable_title"}),
+ ))
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
- item["replace"]["Title"] = get_link(item["url"], item["Title"])
+ item["replace"]["Title"] = get_link(
+ item["url"], item["Title"])
return item
+
schema = ATFolderSchema.copy()
+
+
class BatchLabels(ATFolder):
implements(IBatchLabels, IHideActionsMenu)
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(BatchLabels, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_containers.py b/src/bika/lims/controlpanel/bika_containers.py
index 9ad79a59d2..6b8603d57a 100644
--- a/src/bika/lims/controlpanel/bika_containers.py
+++ b/src/bika/lims/controlpanel/bika_containers.py
@@ -18,8 +18,8 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
+import collections
+
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -28,7 +28,10 @@
from bika.lims.permissions import AddContainer
from bika.lims.utils import get_link
from bika.lims.utils import get_link_for
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -37,63 +40,71 @@ class ContainersView(BikaListingView):
def __init__(self, context, request):
super(ContainersView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'Container',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=Container',
- 'permission': AddContainer,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "Container",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=Container",
+ "permission": AddContainer,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.title = self.context.translate(_("Containers"))
- self.icon = self.portal_url + "/++resource++bika.lims.images/container_big.png"
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/container_big.png"
+ )
+
self.description = ""
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Container'),
- 'index':'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- 'ContainerType': {'title': _('Container Type'),
- 'toggle': True},
- 'Capacity': {'title': _('Capacity'),
- 'toggle': True},
- 'Pre-preserved': {'title': _('Pre-preserved'),
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Container"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "description",
+ "toggle": True}),
+ ("ContainerType", {
+ "title": _("Container Type"),
+ "toggle": True}),
+ ("Capacity", {
+ "title": _("Capacity"),
+ "toggle": True}),
+ ("Pre-preserved", {
+ "title": _("Pre-preserved"),
+ "toggle": True}),
+ ))
- self.review_states = [ # leave these titles and ids alone
- {'id':'default',
- 'contentFilter': {'is_active': True},
- 'title': _('Active'),
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title',
- 'Description',
- 'ContainerType',
- 'Capacity',
- 'Pre-preserved']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title',
- 'Description',
- 'ContainerType',
- 'Capacity',
- 'Pre-preserved']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'transitions': [],
- 'columns': ['Title',
- 'Description',
- 'ContainerType',
- 'Capacity',
- 'Pre-preserved']},
+ self.review_states = [
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
@@ -108,19 +119,23 @@ def folderitem(self, obj, item, index):
})
if obj.getPrePreserved():
- item["after"]["Pre-preserved"] = get_link_for(obj.getPreservation())
+ item["after"]["Pre-preserved"] = get_link_for(
+ obj.getPreservation())
+
+ item["replace"]["Title"] = get_link(
+ item["url"], item["Title"])
- item["replace"]["Title"] = get_link(item["url"], item["Title"])
return item
schema = ATFolderSchema.copy()
+
class Containers(ATFolder):
implements(IContainers, IHideActionsMenu)
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(Containers, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_containertypes.py b/src/bika/lims/controlpanel/bika_containertypes.py
index f739d9b2e9..5b42b0f613 100644
--- a/src/bika/lims/controlpanel/bika_containertypes.py
+++ b/src/bika/lims/controlpanel/bika_containertypes.py
@@ -18,8 +18,8 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
+import collections
+
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -27,7 +27,10 @@
from bika.lims.interfaces import IContainerTypes
from bika.lims.permissions import AddContainerType
from bika.lims.utils import get_link
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -36,53 +39,69 @@ class ContainerTypesView(BikaListingView):
def __init__(self, context, request):
super(ContainerTypesView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'ContainerType',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=ContainerType',
- 'permission': AddContainerType,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "ContainerType",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _('Add'): {
+ 'url': 'createObject?type_name=ContainerType',
+ 'permission': AddContainerType,
+ 'icon': '++resource++bika.lims.images/add.png'}
+ }
+
self.title = self.context.translate(_("Container Types"))
- self.icon = self.portal_url + "/++resource++bika.lims.images/container_big.png"
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/container_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Container Type'),
- 'index':'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Title"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "Description",
+ "toggle": True,
+ }),
+ ))
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title',
- 'Description']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title',
- 'Description']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title',
- 'Description']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
obj = api.get_object(obj)
item["Description"] = obj.Description()
- item["replace"]["Title"] = get_link(item["url"], item["Title"])
+ item["replace"]["Title"] = get_link(
+ item["url"], item["Title"])
return item
@@ -95,6 +114,5 @@ class ContainerTypes(ATFolder):
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(ContainerTypes, PROJECTNAME)
-
diff --git a/src/bika/lims/controlpanel/bika_identifiertypes.py b/src/bika/lims/controlpanel/bika_identifiertypes.py
deleted file mode 100644
index 91157de462..0000000000
--- a/src/bika/lims/controlpanel/bika_identifiertypes.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of SENAITE.CORE.
-#
-# SENAITE.CORE is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright 2018-2020 by it's authors.
-# Some rights reserved, see README and LICENSE.
-
-from bika.lims.config import PROJECTNAME
-from bika.lims.interfaces import IIdentifierTypes
-from plone.app.folder.folder import ATFolder
-from plone.app.folder.folder import ATFolderSchema
-from Products.Archetypes.public import registerType
-from Products.ATContentTypes.content import schemata
-from senaite.core.interfaces import IHideActionsMenu
-from zope.interface.declarations import implements
-
-
-schema = ATFolderSchema.copy()
-
-
-class IdentifierTypes(ATFolder):
- implements(IIdentifierTypes, IHideActionsMenu)
- displayContentsTab = False
- schema = schema
-
-
-schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
-
-registerType(IdentifierTypes, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_idserver.py b/src/bika/lims/controlpanel/bika_idserver.py
deleted file mode 100644
index 3736fd975e..0000000000
--- a/src/bika/lims/controlpanel/bika_idserver.py
+++ /dev/null
@@ -1,79 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of SENAITE.CORE.
-#
-# SENAITE.CORE is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright 2018-2020 by it's authors.
-# Some rights reserved, see README and LICENSE.
-
-from AccessControl import ClassSecurityInfo
-from App.class_init import InitializeClass
-from OFS.SimpleItem import SimpleItem
-from Products.CMFCore import permissions
-from Products.CMFCore.utils import getToolByName
-from bika.lims import bikaMessageFactory as _
-from bika.lims.utils import t
-from bika.lims.interfaces import IIdServer
-from zope.interface.declarations import implements
-from hashlib import sha1
-import App,os,sys,random,time,urllib,hmac
-
-try:
- from zope.component.hooks import getSite
-except:
- # Plone < 4.3
- from zope.app.component.hooks import getSite
-
-class IDServerUnavailable(Exception):
- pass
-
-class bika_idserver(object):
-
- implements(IIdServer)
- security = ClassSecurityInfo()
-
- security.declarePublic('generate_id')
- def generate_id(self, portal_type, batch_size = None):
- """ Generate a new id for 'portal_type'
- """
- plone = getSite()
- portal_id = plone.getId()
-
- if portal_type == 'News Item':
- portal_type = 'NewsItem'
-
- idserver_url = os.environ.get('IDServerURL')
- try:
- if batch_size:
- # GET
- f = urllib.urlopen('%s/%s%s?%s' % (
- idserver_url,
- portal_id,
- portal_type,
- urllib.urlencode({'batch_size': batch_size}))
- )
- else:
- f = urllib.urlopen('%s/%s%s' % (
- idserver_url, portal_id, portal_type
- )
- )
- id = f.read()
- f.close()
- except:
- from sys import exc_info
- info = exc_info()
- import zLOG; zLOG.LOG('INFO', 0, '', 'generate_id raised exception: %s, %s \n idserver_url: %s' % (info[0], info[1], idserver_url))
- raise IDServerUnavailable(_('ID Server unavailable'))
- return id
diff --git a/src/bika/lims/controlpanel/bika_instruments.py b/src/bika/lims/controlpanel/bika_instruments.py
index 585aadda46..68c0e07fa2 100644
--- a/src/bika/lims/controlpanel/bika_instruments.py
+++ b/src/bika/lims/controlpanel/bika_instruments.py
@@ -20,8 +20,6 @@
import collections
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -31,10 +29,11 @@
from bika.lims.utils import get_link
from plone.app.folder.folder import ATFolder
from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
-
# TODO: Separate content and view into own modules!
diff --git a/src/bika/lims/controlpanel/bika_instrumenttypes.py b/src/bika/lims/controlpanel/bika_instrumenttypes.py
index c3d13ad61d..8b3f07b235 100644
--- a/src/bika/lims/controlpanel/bika_instrumenttypes.py
+++ b/src/bika/lims/controlpanel/bika_instrumenttypes.py
@@ -18,8 +18,8 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
+import collections
+
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -27,7 +27,10 @@
from bika.lims.interfaces import IInstrumentTypes
from bika.lims.permissions import AddInstrumentType
from bika.lims.utils import get_link
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -36,44 +39,62 @@ class InstrumentTypesView(BikaListingView):
def __init__(self, context, request):
super(InstrumentTypesView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'InstrumentType',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=InstrumentType',
- 'permission': AddInstrumentType,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "InstrumentType",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _('Add'): {
+ 'url': 'createObject?type_name=InstrumentType',
+ 'permission': AddInstrumentType,
+ 'icon': '++resource++bika.lims.images/add.png'}
+ }
+
self.title = self.context.translate(_("Instrument Types"))
- self.icon = "++resource++bika.lims.images/instrumenttype_big.png"
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/instrumenttype_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Title'),
- 'index': 'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Title"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "Description",
+ "toggle": True,
+ }),
+ ))
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title', 'Description']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title', 'Description']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title', 'Description']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
@@ -91,5 +112,6 @@ class InstrumentTypes(ATFolder):
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(InstrumentTypes, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_labproducts.py b/src/bika/lims/controlpanel/bika_labproducts.py
index 11c989867a..d0c398a024 100644
--- a/src/bika/lims/controlpanel/bika_labproducts.py
+++ b/src/bika/lims/controlpanel/bika_labproducts.py
@@ -18,87 +18,96 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
+import collections
+
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import ILabProducts
from bika.lims.permissions import AddLabProduct
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from bika.lims.utils import get_link
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
-from bika.lims.utils import get_link
-
class LabProductsView(BikaListingView):
def __init__(self, context, request):
super(LabProductsView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'LabProduct',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=LabProduct',
- 'permission': AddLabProduct,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "LabProduct",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=LabProduct",
+ "permission": AddLabProduct,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.title = self.context.translate(_("Lab Products"))
- self.icon = self.portal_url + "/++resource++bika.lims.images/product_big.png"
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/product_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Title'),
- 'index': 'sortable_title',
- 'toggle': True},
- 'Volume': {'title': _('Volume'),
- 'toggle': True},
- 'Unit': {'title': _('Unit'),
- 'toggle': True},
- 'Price': {'title': _('Price'),
- 'index': 'price',
- 'toggle': True},
- 'VATAmount': {'title': _('VAT Amount'),
- 'toggle': True},
- 'TotalPrice': {'title': _('Total Price'),
- 'index': 'price_total',
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Title"),
+ "index": "sortable_title",
+ "toggle": True}),
+ ("Volume", {
+ "title": _("Volume"),
+ "toggle": True}),
+ ("Unit", {
+ "title": _("Unit"),
+ "toggle": True}),
+ ("Price", {
+ "title": _("Price"),
+ "index": "price",
+ "toggle": True}),
+ ("VATAmount", {
+ "title": _("VAT Amount"),
+ "toggle": True}),
+ ("TotalPrice", {
+ "title": _("Total Price"),
+ "index": "price_total",
+ "toggle": True}),
+ ))
+
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title',
- 'Volume',
- 'Unit',
- 'Price',
- 'VATAmount',
- 'TotalPrice']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title',
- 'Volume',
- 'Unit',
- 'Price',
- 'VATAmount',
- 'TotalPrice']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title',
- 'Volume',
- 'Unit',
- 'Price',
- 'VATAmount',
- 'TotalPrice']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
@@ -115,10 +124,13 @@ def folderitem(self, obj, item, index):
schema = ATFolderSchema.copy()
+
+
class LabProducts(ATFolder):
implements(ILabProducts, IHideActionsMenu)
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(LabProducts, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_manufacturers.py b/src/bika/lims/controlpanel/bika_manufacturers.py
index 2410a302d9..896ac206cb 100644
--- a/src/bika/lims/controlpanel/bika_manufacturers.py
+++ b/src/bika/lims/controlpanel/bika_manufacturers.py
@@ -18,16 +18,19 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
-from bika.lims import bikaMessageFactory as _
+import collections
+
from bika.lims import api
+from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import IManufacturers
from bika.lims.permissions import AddManufacturer
from bika.lims.utils import get_link
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -36,44 +39,62 @@ class ManufacturersView(BikaListingView):
def __init__(self, context, request):
super(ManufacturersView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'Manufacturer',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=Manufacturer',
- 'permission': AddManufacturer,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "Manufacturer",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=Manufacturer",
+ "permission": AddManufacturer,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.title = self.context.translate(_("Manufacturers"))
- self.icon = "++resource++bika.lims.images/manufacturer_big.png"
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/manufacturer_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Title'),
- 'index': 'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Manufacturer"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "Description",
+ "toggle": True,
+ }),
+ ))
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title', 'Description']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title', 'Description']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title', 'Description']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
@@ -91,5 +112,6 @@ class Manufacturers(ATFolder):
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(Manufacturers, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_preservations.py b/src/bika/lims/controlpanel/bika_preservations.py
index e7aec04cfc..5141a84dea 100644
--- a/src/bika/lims/controlpanel/bika_preservations.py
+++ b/src/bika/lims/controlpanel/bika_preservations.py
@@ -18,8 +18,8 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
+import collections
+
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -27,7 +27,10 @@
from bika.lims.interfaces import IPreservations
from bika.lims.permissions import AddPreservation
from bika.lims.utils import get_link
-from plone.app.folder.folder import ATFolder, ATFolderSchema
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -36,53 +39,69 @@ class PreservationsView(BikaListingView):
def __init__(self, context, request):
super(PreservationsView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'Preservation',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=Preservation',
- 'permission': AddPreservation,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "Preservation",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=Preservation",
+ "permission": AddPreservation,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.title = self.context.translate(_("Preservations"))
- self.icon = self.portal_url + "/++resource++bika.lims.images/preservation_big.png"
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/preservation_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Preservation'),
- 'index':'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Preservation"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "Description",
+ "toggle": True,
+ }),
+ ))
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title',
- 'Description']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title',
- 'Description']},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title',
- 'Description']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
obj = api.get_object(obj)
item["Description"] = obj.Description()
- item["replace"]["Title"] = get_link(item["url"], item["Title"])
+ item["replace"]["Title"] = get_link(
+ item["url"], item["Title"])
return item
@@ -94,5 +113,6 @@ class Preservations(ATFolder):
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
+
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(Preservations, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_reflexrulefolder.py b/src/bika/lims/controlpanel/bika_reflexrulefolder.py
index 13f874d3d0..dfe95bb00b 100644
--- a/src/bika/lims/controlpanel/bika_reflexrulefolder.py
+++ b/src/bika/lims/controlpanel/bika_reflexrulefolder.py
@@ -18,20 +18,20 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
-from Products.CMFCore import permissions
-from Products.CMFCore.utils import getToolByName
+import collections
+
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import IReflexRuleFolder
-from bika.lims.permissions import ManageBika, AddReflexRule
+from bika.lims.permissions import AddReflexRule
from bika.lims.utils import get_link
from bika.lims.utils import get_link_for
from plone.app.folder.folder import ATFolder
from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -40,21 +40,35 @@ class ReflexRuleFolderView(BikaListingView):
def __init__(self, context, request):
super(ReflexRuleFolderView, self).__init__(context, request)
+
self.catalog = "portal_catalog"
+
self.contentFilter = {
- 'portal_type': 'ReflexRule',
- 'path': {
+ "portal_type": "ReflexRule",
+ "path": {
"query": "/".join(self.context.getPhysicalPath()),
"level": 0
},
}
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=ReflexRule",
+ "permission": AddReflexRule,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.show_select_row = False
self.show_select_column = True
- self.icon = self.portal_url +\
- "/++resource++bika.lims.images/reflexrule_big.png"
+ self.pagesize = 25
+
self.title = self.context.translate(_("Reflex rules folder"))
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/reflexrule_big.png"
+ )
+
self.columns = {
'Title': {
'title': _('Reflex Rule'),
@@ -65,41 +79,37 @@ def __init__(self, context, request):
'index': 'sortable_title'
}
}
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Reflex Rule"),
+ "index": "sortable_title"}),
+ ("Method", {
+ "title": _("Method"),
+ "index": "sortable_title"
+ }),
+ ))
+
self.review_states = [
- {'id': 'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'columns': ['Title', 'Method', ]},
- {'id': 'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'columns': ['Title', 'Method', ]},
- {'id': 'all',
- 'title': _('All'),
- 'contentFilter': {},
- 'columns': ['Title', 'Method', ]},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
- def __call__(self):
- mtool = getToolByName(self.context, 'portal_membership')
- if mtool.checkPermission(
- permissions.ModifyPortalContent,
- self.context):
- self.context_actions[_('Add Reflex rule')] = {
- 'url': 'createObject?type_name=ReflexRule',
- 'permission': AddReflexRule,
- 'icon': '++resource++bika.lims.images/add.png'
- }
- if not mtool.checkPermission(ManageBika, self.context):
- self.show_select_column = False
- self.review_states = [
- {'id': 'default',
- 'title': _('All'),
- 'contentFilter': {},
- 'columns': ['Title']}
- ]
- return super(ReflexRuleFolderView, self).__call__()
-
def folderitem(self, obj, item, index):
obj = api.get_object(obj)
method = obj.getMethod()
@@ -120,9 +130,5 @@ class ReflexRuleFolder(ATFolder):
schema = schema
-schemata.finalizeATCTSchema(
- schema,
- folderish=True,
- moveDiscussion=False)
-
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(ReflexRuleFolder, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_sampleconditions.py b/src/bika/lims/controlpanel/bika_sampleconditions.py
index 932371b2e2..f797499d0a 100644
--- a/src/bika/lims/controlpanel/bika_sampleconditions.py
+++ b/src/bika/lims/controlpanel/bika_sampleconditions.py
@@ -79,25 +79,23 @@ def __init__(self, context, request):
self.review_states = [
{
- 'id': 'default',
- 'title': _('All'),
- 'contentFilter': {},
- 'transitions': [{'id': 'empty'}, ],
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
"columns": self.columns.keys(),
}, {
- 'id': 'active',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id': 'deactivate'}, ],
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
"columns": self.columns.keys(),
}, {
- 'id': 'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id': 'activate'}, ],
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
"columns": self.columns.keys(),
-
- }
+ },
]
def folderitem(self, obj, item, index):
diff --git a/src/bika/lims/controlpanel/bika_samplematrices.py b/src/bika/lims/controlpanel/bika_samplematrices.py
index 167c6310d9..78eb06ba79 100644
--- a/src/bika/lims/controlpanel/bika_samplematrices.py
+++ b/src/bika/lims/controlpanel/bika_samplematrices.py
@@ -18,6 +18,8 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
+import collections
+
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
@@ -36,51 +38,66 @@ class SampleMatricesView(BikaListingView):
def __init__(self, context, request):
super(SampleMatricesView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'SampleMatrix',
- 'sort_on': 'sortable_title'}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "SampleMatrix",
+ "sort_on": "sortable_title",
+ }
+
self.context_actions = {_('Add'): {
'url': 'createObject?type_name=SampleMatrix',
'permission': AddSampleMatrix,
'icon': '++resource++bika.lims.images/add.png'
}}
+
self.title = self.context.translate(_("Sample Matrices"))
- self.icon = self.portal_url + \
- "/++resource++bika.lims.images/samplematrix_big.png"
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/samplematrix_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Sample Matrix'),
- 'index': 'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Sample Matrix"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "Description",
+ "toggle": True,
+ }),
+ ))
self.review_states = [
- {'id': 'default',
- 'title': _('All'),
- 'contentFilter': {},
- 'transitions': [{'id': 'empty'}, ],
- 'columns': ['Title', 'Description']},
- {'id': 'active',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id': 'deactivate'}, ],
- 'columns': ['Title', 'Description']},
- {'id': 'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id': 'activate'}, ],
- 'columns': ['Title', 'Description']}
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
- item["replace"]["Title"] = get_link(item["url"], item["Title"])
+ item["replace"]["Title"] = get_link(
+ item["url"], item["Title"])
return item
diff --git a/src/bika/lims/controlpanel/bika_samplepoints.py b/src/bika/lims/controlpanel/bika_samplepoints.py
index 267cf1776f..b9e4621c12 100644
--- a/src/bika/lims/controlpanel/bika_samplepoints.py
+++ b/src/bika/lims/controlpanel/bika_samplepoints.py
@@ -19,30 +19,21 @@
# Some rights reserved, see README and LICENSE.
import collections
-import json
-
-import plone
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
-from Products.CMFCore.permissions import ModifyPortalContent
-from Products.CMFCore.utils import getToolByName
-from Products.CMFPlone.utils import safe_unicode
-from plone.app.folder.folder import ATFolder
-from plone.app.folder.folder import ATFolderSchema
-from senaite.core.interfaces import IHideActionsMenu
-from zope.interface.declarations import implements
from bika.lims import api
from bika.lims import bikaMessageFactory as _
-from bika.lims.api.security import check_permission
-from bika.lims.browser import BrowserView
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.catalog import SETUP_CATALOG
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import ISamplePoints
from bika.lims.permissions import AddSamplePoint
from bika.lims.utils import get_link_for
-
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
+from senaite.core.interfaces import IHideActionsMenu
+from zope.interface.declarations import implements
# TODO: Separate content and view into own modules!
@@ -140,92 +131,6 @@ def folderitem(self, obj, item, index):
return item
-class ajax_SamplePoints(BrowserView):
- """ The autocomplete data source for sample point selection widgets.
- Returns a JSON list of sample point titles.
-
- Request parameters:
-
- - sampletype: if specified, it's expected to be the title
- of a SamplePoint object. Optionally, the string 'Lab: ' might be
- prepended, to distinguish between Lab and Client objects.
-
- - term: the string which will be searched against all SamplePoint
- titles.
-
- - _authenticator: The plone.protect authenticator.
- """
-
- def filter_list(self, items, searchterm):
- if searchterm and len(searchterm) < 3:
- # Items that start with A or AA
- res = [s.getObject() for s in items
- if s.title.lower().startswith(searchterm)]
- if not res:
- # or, items that contain A or AA
- res = [s.getObject() for s in items
- if s.title.lower().find(searchterm) > -1]
- else:
- # or, items that contain searchterm.
- res = [s.getObject() for s in items
- if s.title.lower().find(searchterm) > -1]
- return res
-
- def __call__(self):
- plone.protect.CheckAuthenticator(self.request)
- bsc = getToolByName(self.context, 'bika_setup_catalog')
- term = safe_unicode(self.request.get('term', '')).lower()
- items = []
- if not term:
- return json.dumps(items)
- # Strip "Lab: " from sample point title
- term = term.replace("%s: " % _("Lab"), "")
- sampletype = safe_unicode(self.request.get("sampletype", ""))
- if sampletype and len(sampletype) > 1:
- st = bsc(
- portal_type="SampleType",
- title=sampletype,
- is_active=True,
- )
- if not st:
- return json.dumps([])
- st = st[0].getObject()
- items = [o.Title() for o in st.getSamplePoints()]
-
- if not items:
- client_items = lab_items = []
-
- # User (client) sample points
- if self.context.portal_type in ("Client", "AnalysisRequest"):
- if self.context.portal_type == "Client":
- client_path = self.context.getPhysicalPath()
- else:
- client_path = self.context.aq_parent.getPhysicalPath()
- client_items = list(
- bsc(portal_type="SamplePoint",
- path={"query": "/".join(client_path), "level": 0},
- is_active=True,
- sort_on="sortable_title"))
-
- # Global (lab) sample points
- sample_points = self.context.bika_setup.bika_samplepoints
- lab_path = sample_points.getPhysicalPath()
- lab_items = list(
- bsc(portal_type="SamplePoint",
- path={"query": "/".join(lab_path), "level": 0},
- is_active=True,
- sort_on="sortable_title"))
- client_items = [callable(s.Title) and s.Title() or s.title
- for s in self.filter_list(client_items, term)]
- lab_items = [callable(s.Title) and s.Title() or s.title
- for s in self.filter_list(lab_items, term)]
- lab_items = ["%s: %s" % (_("Lab"), safe_unicode(i))
- for i in lab_items]
- items = client_items + lab_items
-
- return json.dumps(items)
-
-
schema = ATFolderSchema.copy()
diff --git a/src/bika/lims/controlpanel/bika_sampletypes.py b/src/bika/lims/controlpanel/bika_sampletypes.py
index 1b9cd43397..9e6c7b803c 100644
--- a/src/bika/lims/controlpanel/bika_sampletypes.py
+++ b/src/bika/lims/controlpanel/bika_sampletypes.py
@@ -19,29 +19,21 @@
# Some rights reserved, see README and LICENSE.
import collections
-import json
-
-import plone
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
-from Products.CMFCore.permissions import ModifyPortalContent
-from Products.CMFCore.utils import getToolByName
-from Products.CMFPlone.utils import safe_unicode
-from plone.app.folder.folder import ATFolder
-from plone.app.folder.folder import ATFolderSchema
-from senaite.core.interfaces import IHideActionsMenu
-from zope.interface.declarations import implements
from bika.lims import api
from bika.lims import bikaMessageFactory as _
-from bika.lims.api.security import check_permission
-from bika.lims.browser import BrowserView
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.catalog import SETUP_CATALOG
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import ISampleTypes
from bika.lims.permissions import AddSampleType
from bika.lims.utils import get_link_for
+from plone.app.folder.folder import ATFolder
+from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
+from senaite.core.interfaces import IHideActionsMenu
+from zope.interface.declarations import implements
# TODO: Separate content and view into own modules!
@@ -161,6 +153,18 @@ def folderitem(self, obj, item, index):
container_type = obj.getContainerType()
item["replace"]["ContainerType"] = get_link_for(container_type)
+ # Hazardous
+ hazardous = obj.getHazardous()
+ item["getHazardous"] = hazardous
+
+ # Prefix
+ prefix = obj.getPrefix()
+ item["getPrefix"] = prefix
+
+ # Minimum Volume
+ vol = obj.getMinimumVolume()
+ item["getMinimumVolume"] = vol
+
# Hide sample points assigned to this sample type that do not belong
# to the same container (Client or Setup)
sample_points = obj.getSamplePoints()
@@ -179,65 +183,6 @@ def folderitem(self, obj, item, index):
return item
-class ajax_SampleTypes(BrowserView):
- """Autocomplete data source for sample types field
-
- return JSON data [string,string]
- if "samplepoint" is in the request, it's expected to be a title string
- The objects returned will be filtered by samplepoint's SampleTypes.
- if no items are found, all items are returned.
-
- If term is a one or two letters, return items that begin with them
- If there aren't any, return items that contain them
- """
- def __call__(self):
- plone.protect.CheckAuthenticator(self.request)
- bsc = getToolByName(self.context, "bika_setup_catalog")
- term = safe_unicode(self.request.get("term", "")).lower()
- items = []
- if not term:
- return json.dumps(items)
- samplepoint = safe_unicode(self.request.get("samplepoint", ""))
- # Strip "Lab: " from sample point titles
- samplepoint = samplepoint.replace("%s: " % _("Lab"), "")
- if samplepoint and len(samplepoint) > 1:
- sp = bsc(
- portal_type="SamplePoint",
- is_active=True,
- title=samplepoint
- )
- if not sp:
- return json.dumps([])
- sp = sp[0].getObject()
- items = sp.getSampleTypes()
- if not items:
- items = bsc(
- portal_type="SampleType",
- is_active=True,
- sort_on="sortable_title",
- )
- if term and len(term) < 3:
- # Items that start with A or AA
- items = [
- s.getObject() for s in items
- if s.title.lower().startswith(term)
- ]
- if not items:
- # or, items that contain A or AA
- items = [
- s.getObject() for s in items
- if s.title.lower().find(term) > -1]
- else:
- # or, items that contain term.
- items = [
- s.getObject() for s in items
- if s.title.lower().find(term) > -1]
-
- items = [callable(s.Title) and s.Title() or s.title
- for s in items]
- return json.dumps(items)
-
-
schema = ATFolderSchema.copy()
diff --git a/src/bika/lims/controlpanel/bika_samplingdeviations.py b/src/bika/lims/controlpanel/bika_samplingdeviations.py
index c644b6445b..47a86fab91 100644
--- a/src/bika/lims/controlpanel/bika_samplingdeviations.py
+++ b/src/bika/lims/controlpanel/bika_samplingdeviations.py
@@ -65,7 +65,7 @@ def __init__(self, context, request):
self.columns = collections.OrderedDict((
("Title", {
- "title": _("Sampling Deviationn"),
+ "title": _("Sampling Deviation"),
"index": "sortable_title"}),
("Description", {
"title": _("Description"),
diff --git a/src/bika/lims/controlpanel/bika_samplingrounds.py b/src/bika/lims/controlpanel/bika_samplingrounds.py
deleted file mode 100644
index da97ad498b..0000000000
--- a/src/bika/lims/controlpanel/bika_samplingrounds.py
+++ /dev/null
@@ -1,35 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of SENAITE.CORE.
-#
-# SENAITE.CORE is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright 2018-2020 by it's authors.
-# Some rights reserved, see README and LICENSE.
-
-from plone.dexterity.content import Container
-from plone.supermodel import model
-from zope.interface import implements
-
-
-# TODO: Legacy type. Remove after 1.3.3
-class ISamplingRounds(model.Schema):
- """ A Sampling Rounds container.
- """
-
-
-# TODO: Legacy type. Remove after 1.3.3
-class SamplingRounds(Container):
- implements(ISamplingRounds)
- displayContentsTab = False
diff --git a/src/bika/lims/controlpanel/bika_setupitems.py b/src/bika/lims/controlpanel/bika_setupitems.py
deleted file mode 100644
index 2437ad581b..0000000000
--- a/src/bika/lims/controlpanel/bika_setupitems.py
+++ /dev/null
@@ -1,69 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of SENAITE.CORE.
-#
-# SENAITE.CORE is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright 2018-2020 by it's authors.
-# Some rights reserved, see README and LICENSE.
-
-from bika.lims import bikaMessageFactory as _
-from bika.lims.browser.bika_listing import BikaListingView
-
-
-class BikaSetupItemsView(BikaListingView):
-
- def __init__(self, context, request, typename, iconfilename):
- super(BikaSetupItemsView, self).__init__(context, request)
- self.show_select_column = True
- self.icon = self.portal_url + "/++resource++bika.lims.images/" + iconfilename
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {
- 'portal_type': typename,
- 'sort_on': 'sortable_title'
- }
- self.context_actions = {
- _('Add'): {
- 'url': 'createObject?type_name='+typename,
- 'icon': '++resource++bika.lims.images/add.png'
- }
- }
- self.columns = {
- 'Title': {
- 'title': _('Title'),
- 'index': 'sortable_title',
- 'replace_url': 'absolute_url'
- },
- 'Description': {
- 'title': _('Description'),
- 'index': 'description',
- 'attr': 'Description'
- },
- }
- self.review_states = [
- {'id': 'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id': 'deactivate'}, ],
- 'columns': ['Title', 'Description']},
- {'id': 'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id': 'activate'}, ],
- 'columns': ['Title', 'Description']},
- {'id': 'all',
- 'title': _('All'),
- 'contentFilter': {},
- 'columns': ['Title', 'Description']},
- ]
diff --git a/src/bika/lims/controlpanel/bika_srtemplates.py b/src/bika/lims/controlpanel/bika_srtemplates.py
deleted file mode 100644
index 233dc97730..0000000000
--- a/src/bika/lims/controlpanel/bika_srtemplates.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of SENAITE.CORE.
-#
-# SENAITE.CORE is free software: you can redistribute it and/or modify it under
-# the terms of the GNU General Public License as published by the Free Software
-# Foundation, version 2.
-#
-# This program is distributed in the hope that it will be useful, but WITHOUT
-# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
-# details.
-#
-# You should have received a copy of the GNU General Public License along with
-# this program; if not, write to the Free Software Foundation, Inc., 51
-# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-#
-# Copyright 2018-2020 by it's authors.
-# Some rights reserved, see README and LICENSE.
-
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
-from plone.app.folder.folder import ATFolder
-from plone.app.folder.folder import ATFolderSchema
-from senaite.core.interfaces import IHideActionsMenu
-from zope.interface.declarations import implements
-
-from bika.lims.config import PROJECTNAME
-from bika.lims.interfaces import ISamplingRoundTemplates
-
-schema = ATFolderSchema.copy()
-
-
-# TODO: Legacy type. Remove after 1.3.3
-class SRTemplates(ATFolder):
- implements(ISamplingRoundTemplates, IHideActionsMenu)
- displayContentsTab = False
- schema = schema
-
-
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
-atapi.registerType(SRTemplates, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_storagelocations.py b/src/bika/lims/controlpanel/bika_storagelocations.py
index a25d16a845..9b4bcd494d 100644
--- a/src/bika/lims/controlpanel/bika_storagelocations.py
+++ b/src/bika/lims/controlpanel/bika_storagelocations.py
@@ -18,87 +18,105 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
-import json
+import collections
-import plone
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import PloneMessageFactory as _p
-from Products.Archetypes import atapi
-from Products.CMFCore.utils import getToolByName
-from Products.CMFPlone.utils import safe_unicode
from bika.lims import api
from bika.lims import bikaMessageFactory as _
-from bika.lims.browser import BrowserView
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import PROJECTNAME
from bika.lims.interfaces import IClient
from bika.lims.interfaces import IStorageLocations
from bika.lims.permissions import AddStorageLocation
from bika.lims.utils import get_link
+from bika.lims.utils import get_link_for
from plone.app.folder.folder import ATFolder
from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
-from bika.lims.utils import get_link
-
class StorageLocationsView(BikaListingView):
def __init__(self, context, request):
super(StorageLocationsView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'StorageLocation',
- 'sort_on': 'sortable_title'}
- self.context_actions = {_('Add'):
- {'url': 'createObject?type_name=StorageLocation',
- 'permission': AddStorageLocation,
- 'icon': '++resource++bika.lims.images/add.png'}}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "StorageLocation",
+ "sort_on": "sortable_title",
+ }
+
+ self.context_actions = {
+ _("Add"): {
+ "url": "createObject?type_name=StorageLocation",
+ "permission": AddStorageLocation,
+ "icon": "++resource++bika.lims.images/add.png"}
+ }
+
self.title = self.context.translate(_("Storage Locations"))
- self.icon = self.portal_url + "/++resource++bika.lims.images/storagelocation_big.png"
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/storagelocation_big.png"
+ )
self.description = ""
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Storage Location'),
- 'index':'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- 'SiteTitle': {'title': _p('Site Title'),
- 'toggle': True},
- 'SiteCode': {'title': _p('Site Code'),
- 'toggle': True},
- 'LocationTitle': {'title': _p('Location Title'),
- 'toggle': True},
- 'LocationCode': {'title': _p('Location Code'),
- 'toggle': True},
- 'ShelfTitle': {'title': _p('Shelf Title'),
- 'toggle': True},
- 'ShelfCode': {'title': _p('Shelf Code'),
- 'toggle': True},
- 'Owner': {'title': _p('Owner'),
- 'toggle': True},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Storage Location"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "description",
+ "toggle": True}),
+ ("SiteTitle", {
+ "title": _("Site Title"),
+ "toggle": True}),
+ ("SiteCode", {
+ "title": _("Site Code"),
+ "toggle": True}),
+ ("LocationTitle", {
+ "title": _("Location Title"),
+ "toggle": True}),
+ ("LocationCode", {
+ "title": _("Location Code"),
+ "toggle": True}),
+ ("ShelfTitle", {
+ "title": _("Shelf Title"),
+ "toggle": True}),
+ ("ShelfCode", {
+ "title": _("Shelf Code"),
+ "toggle": True}),
+ ("Owner", {
+ "title": _("Owner"),
+ "toggle": True}),
+ ))
self.review_states = [
- {'id':'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id':'deactivate'}, ],
- 'columns': ['Title', 'Description', 'Owner', 'SiteTitle', 'SiteCode', 'LocationTitle', 'LocationCode', 'ShelfTitle', 'ShelfCode']},
- {'id':'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id':'activate'}, ],
- 'columns': ['Title', 'Description', 'Owner', 'SiteTitle', 'SiteCodeShelfCode' ]},
- {'id':'all',
- 'title': _('All'),
- 'contentFilter':{},
- 'columns': ['Title', 'Description', 'Owner', 'SiteTitle', 'SiteCodeShelfCode' ]},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {"is_active": False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
@@ -106,11 +124,22 @@ def folderitem(self, obj, item, index):
item["Description"] = obj.Description()
item["replace"]["Title"] = get_link(item["url"], item["Title"])
+ item["SiteTitle"] = obj.getSiteTitle()
+ item["SiteCode"] = obj.getSiteCode()
+ item["LocationTitle"] = obj.getLocationTitle()
+ item["LocationCode"] = obj.getLocationCode()
+ item["ShelfTitle"] = obj.getShelfTitle()
+ item["ShelfCode"] = obj.getShelfCode()
+
parent = api.get_parent(obj)
if IClient.providedBy(parent):
item["Owner"] = api.get_title(parent)
+ item["replace"]["Owner"] = get_link_for(parent)
else:
- item["Owner"] = self.context.bika_setup.laboratory.Title()
+ lab = self.context.bika_setup.laboratory
+ item["Owner"] = lab.Title()
+ item["replace"]["Owner"] = get_link_for(lab)
+
return item
@@ -122,75 +151,6 @@ class StorageLocations(ATFolder):
displayContentsTab = False
schema = schema
-schemata.finalizeATCTSchema(schema, folderish = True, moveDiscussion = False)
-atapi.registerType(StorageLocations, PROJECTNAME)
-
-
-class ajax_StorageLocations(BrowserView):
- """ The autocomplete data source for storage location selection widgets.
- Returns a JSON list of storage location titles.
- Request parameters:
-
- - term: the string which will be searched against all Storage Location
- titles.
-
- - _authenticator: The plone.protect authenticator.
-
- """
-
- def filter_list(self, items, searchterm):
- if searchterm and len(searchterm) < 3:
- # Items that start with A or AA
- res = [s.getObject()
- for s in items
- if s.title.lower().startswith(searchterm)]
- if not res:
- # or, items that contain A or AA
- res = [s.getObject()
- for s in items
- if s.title.lower().find(searchterm) > -1]
- else:
- # or, items that contain searchterm.
- res = [s.getObject()
- for s in items
- if s.title.lower().find(searchterm) > -1]
- return res
-
- def __call__(self):
- plone.protect.CheckAuthenticator(self.request)
- bsc = getToolByName(self.context, 'bika_setup_catalog')
- term = safe_unicode(self.request.get('term', '')).lower()
- if not term:
- return json.dumps([])
-
- client_items = lab_items = []
-
- # User (client) storage locations
- if self.context.portal_type == 'Client':
- client_path = self.context.getPhysicalPath()
- client_items = list(
- bsc(portal_type = "StorageLocation",
- path = {"query": "/".join(client_path), "level" : 0 },
- is_active = True,
- sort_on='sortable_title'))
-
- # Global (lab) storage locations
- lab_path = \
- self.context.bika_setup.bika_storagelocations.getPhysicalPath()
- lab_items = list(
- bsc(portal_type = "StorageLocation",
- path = {"query": "/".join(lab_path), "level" : 0 },
- is_active = True,
- sort_on='sortable_title'))
-
- client_items = [callable(s.Title) and s.Title() or s.title
- for s in self.filter_list(client_items, term)]
- lab_items = [callable(s.Title) and s.Title() or s.title
- for s in self.filter_list(lab_items, term)]
- lab_items = ["%s: %s" % (_("Lab"), safe_unicode(i))
- for i in lab_items]
-
- items = client_items + lab_items
-
- return json.dumps(items)
+schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
+atapi.registerType(StorageLocations, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/bika_subgroups.py b/src/bika/lims/controlpanel/bika_subgroups.py
index d7ed71b85d..a3d1ee44cd 100644
--- a/src/bika/lims/controlpanel/bika_subgroups.py
+++ b/src/bika/lims/controlpanel/bika_subgroups.py
@@ -18,9 +18,9 @@
# Copyright 2018-2020 by it's authors.
# Some rights reserved, see README and LICENSE.
+import collections
+
from AccessControl.SecurityInfo import ClassSecurityInfo
-from Products.ATContentTypes.content import schemata
-from Products.Archetypes import atapi
from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.bika_listing import BikaListingView
@@ -30,6 +30,8 @@
from bika.lims.utils import get_link
from plone.app.folder.folder import ATFolder
from plone.app.folder.folder import ATFolderSchema
+from Products.Archetypes import atapi
+from Products.ATContentTypes.content import schemata
from senaite.core.interfaces import IHideActionsMenu
from zope.interface.declarations import implements
@@ -38,55 +40,73 @@ class SubGroupsView(BikaListingView):
def __init__(self, context, request):
super(SubGroupsView, self).__init__(context, request)
- self.catalog = 'bika_setup_catalog'
- self.contentFilter = {'portal_type': 'SubGroup',
- 'sort_on': 'sortable_title'}
+
+ self.catalog = "bika_setup_catalog"
+
+ self.contentFilter = {
+ "portal_type": "SubGroup",
+ "sort_on": "sortable_title",
+ }
self.context_actions = {
- _('Add'): {
- 'url': 'createObject?type_name=SubGroup',
- 'permission': AddSubGroup,
- 'icon': '++resource++bika.lims.images/add.png'
+ _("Add"): {
+ "url": "createObject?type_name=SubGroup",
+ "permission": AddSubGroup,
+ "icon": "++resource++bika.lims.images/add.png"
}
}
- self.icon = self.portal_url + \
- "/++resource++bika.lims.images/batch_big.png"
+
self.title = self.context.translate(_("Sub-groups"))
self.description = ""
+ self.icon = "{}/{}".format(
+ self.portal_url,
+ "/++resource++bika.lims.images/batch_big.png"
+ )
self.show_select_row = False
self.show_select_column = True
self.pagesize = 25
- self.columns = {
- 'Title': {'title': _('Sub-group'),
- 'index': 'sortable_title'},
- 'Description': {'title': _('Description'),
- 'index': 'description',
- 'toggle': True},
- 'SortKey': {'title': _('Sort Key')},
- }
+ self.columns = collections.OrderedDict((
+ ("Title", {
+ "title": _("Attachment Type"),
+ "index": "sortable_title"}),
+ ("Description", {
+ "title": _("Description"),
+ "index": "Description",
+ "toggle": True,
+ }),
+ ("SortKey", {
+ "title": _("Sort Key"),
+ "toggle": True,
+ }),
+ ))
self.review_states = [
- {'id': 'default',
- 'title': _('Active'),
- 'contentFilter': {'is_active': True},
- 'transitions': [{'id': 'deactivate'}, ],
- 'columns': ['Title', 'Description', 'SortKey']},
- {'id': 'inactive',
- 'title': _('Inactive'),
- 'contentFilter': {'is_active': False},
- 'transitions': [{'id': 'activate'}, ],
- 'columns': ['Title', 'Description', 'SortKey']},
- {'id': 'all',
- 'title': _('All'),
- 'contentFilter': {},
- 'columns': ['Title', 'Description', 'SortKey']},
+ {
+ "id": "default",
+ "title": _("Active"),
+ "contentFilter": {"is_active": True},
+ "transitions": [{"id": "deactivate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "inactive",
+ "title": _("Inactive"),
+ "contentFilter": {'is_active': False},
+ "transitions": [{"id": "activate"}, ],
+ "columns": self.columns.keys(),
+ }, {
+ "id": "all",
+ "title": _("All"),
+ "contentFilter": {},
+ "columns": self.columns.keys(),
+ },
]
def folderitem(self, obj, item, index):
obj = api.get_object(obj)
item["Description"] = obj.Description()
item["replace"]["Title"] = get_link(item["url"], item["Title"])
+ item["SortKey"] = obj.getSortKey()
return item
@@ -99,5 +119,6 @@ class SubGroups(ATFolder):
displayContentsTab = False
schema = schema
+
schemata.finalizeATCTSchema(schema, folderish=True, moveDiscussion=False)
atapi.registerType(SubGroups, PROJECTNAME)
diff --git a/src/bika/lims/controlpanel/configure.zcml b/src/bika/lims/controlpanel/configure.zcml
index b002664551..4d1a00a2d3 100644
--- a/src/bika/lims/controlpanel/configure.zcml
+++ b/src/bika/lims/controlpanel/configure.zcml
@@ -244,32 +244,6 @@
layer="bika.lims.interfaces.IBikaLIMS"
/>
-
-
-
-
-
-
-
-
-
diff --git a/src/bika/lims/utils/__init__.py b/src/bika/lims/utils/__init__.py
index 92ea505a08..abbe3d7e70 100644
--- a/src/bika/lims/utils/__init__.py
+++ b/src/bika/lims/utils/__init__.py
@@ -23,39 +23,38 @@
import re
import tempfile
import urllib2
+from email import Encoders
+from email.MIMEBase import MIMEBase
+from time import time
+
from AccessControl import ModuleSecurityInfo
from AccessControl import allow_module
from AccessControl import getSecurityManager
from Acquisition import aq_inner
from Acquisition import aq_parent
-from email import Encoders
-from time import time
-
-import types
+from bika.lims import api
+from bika.lims import logger
+from bika.lims.browser import BrowserView
+from bika.lims.interfaces import IClient
+from bika.lims.interfaces import IClientAwareMixin
from DateTime import DateTime
+from plone.protect.utils import addTokenToUrl
+from plone.registry.interfaces import IRegistry
+from plone.subrequest import subrequest
from Products.Archetypes.interfaces.field import IComputedField
from Products.Archetypes.public import DisplayList
-from Products.CMFCore.WorkflowCore import WorkflowException
from Products.CMFCore.utils import getToolByName
+from Products.CMFCore.WorkflowCore import WorkflowException
from Products.CMFPlone.utils import safe_unicode
from Products.DCWorkflow.events import AfterTransitionEvent
-from bika.lims import api
-from bika.lims import logger
-from bika.lims.browser import BrowserView
-from email.MIMEBase import MIMEBase
-from plone.memoize import ram
-from plone.registry.interfaces import IRegistry
-from plone.subrequest import subrequest
-from weasyprint import CSS, HTML
+from weasyprint import CSS
+from weasyprint import HTML
from weasyprint import default_url_fetcher
from zope.component import queryUtility
from zope.event import notify
from zope.i18n import translate
from zope.i18n.locales import locales
-from bika.lims.interfaces import IClient
-from bika.lims.interfaces import IClientAwareMixin
-
ModuleSecurityInfo('email.Utils').declarePublic('formataddr')
allow_module('csv')
@@ -126,19 +125,6 @@ def __call__(self, message):
self.logger.warning(message)
-ModuleSecurityInfo('Products.bika.utils').declarePublic('printfile')
-
-
-def printfile(portal, from_addr, to_addrs, msg):
-
- """ set the path, then the cmd 'lpr filepath'
- temp_path = 'C:/Zope2/Products/Bika/version.txt'
-
- os.system('lpr "%s"' %temp_path)
- """
- pass
-
-
def getUsers(context, roles, allow_empty=True):
""" Present a DisplayList containing users in the specified
list of roles
@@ -695,6 +681,9 @@ def get_link(href, value=None, **kwargs):
return ""
anchor_value = value and value or href
attr = render_html_attributes(**kwargs)
+ # Add a CSRF token
+ if href.startswith("http"):
+ href = addTokenToUrl(href)
return '{}'.format(href, attr, anchor_value)