diff --git a/CHANGES.rst b/CHANGES.rst index a02b05bb2a..e5776a9dc4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Changelog **Added** +- #1515 Moved Setup View into Core - #1506 Specification non-compliant viewlet in Sample - #1506 Sample results ranges out-of-date viewlet in Sample - #1506 Warn icon in analyses when range is not compliant with Specification diff --git a/bika/lims/browser/controlpanel.py b/bika/lims/browser/controlpanel.py index 418e44bf60..ecfdb4ecbe 100644 --- a/bika/lims/browser/controlpanel.py +++ b/bika/lims/browser/controlpanel.py @@ -18,10 +18,96 @@ # Copyright 2018-2020 by it's authors. # Some rights reserved, see README and LICENSE. +import os + +from bika.lims.utils import t from plone.app.controlpanel.overview import OverviewControlPanel +from plone.memoize.volatile import cache +from plone.memoize.volatile import store_on_context +from Products.Five.browser import BrowserView from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile +from bika.lims import api + + +def modified_cache_key(method, self, brain_or_object): + """A cache key that returns the millis of the last modification time + """ + return api.get_modification_date(brain_or_object).millis() class SenaiteOverviewControlPanel(OverviewControlPanel): + """Bootstrapped version of the standard Plone Control Panel + """ template = ViewPageTemplateFile( "templates/plone.app.controlpanel.overview.pt") + + +class SetupView(BrowserView): + """Ordered overview of all Setup Items + """ + template = ViewPageTemplateFile("templates/setupview.pt") + + def __init__(self, context, request): + self.context = context + self.request = request + + def __call__(self): + self.request.set("disable_border", 1) + return self.template() + + @property + def portal(self): + """Returns the Portal Object + """ + return api.get_portal() + + @property + def setup(self): + """Returns the Senaite Setup Object + """ + return api.get_setup() + + @cache(modified_cache_key, store_on_context) + def get_icon_url(self, brain): + """Returns the (big) icon URL for the given catalog brain + """ + icon_url = api.get_icon(brain, html_tag=False) + url, icon = icon_url.rsplit("/", 1) + relative_url = url.lstrip(self.portal.absolute_url()) + name, ext = os.path.splitext(icon) + + # big icons endwith _big + if not name.endswith("_big"): + icon = "{}_big{}".format(name, ext) + + icon_big_url = "/".join([relative_url, icon]) + + # fall back to a default icon if the looked up icon does not exist + if self.context.restrictedTraverse(icon_big_url, None) is None: + icon_big_url = "++resource++bika.lims.images/gears.png" + + return icon_big_url + + def setupitems(self): + """Lookup available setup items + + :returns: catalog brains + """ + query = { + "path": { + "query": api.get_path(self.setup), + "depth": 1, + }, + } + items = api.search(query, "portal_catalog") + # filter out items + items = filter(lambda item: not item.exclude_from_nav, items) + + # sort by (translated) title + def cmp_by_translated_title(brain1, brain2): + title1 = t(api.get_title(brain1)) + title2 = t(api.get_title(brain2)) + # XXX: Python 3 compatibility + return cmp(title1, title2) + + return sorted(items, cmp=cmp_by_translated_title) diff --git a/bika/lims/browser/controlpanel.zcml b/bika/lims/browser/controlpanel.zcml index 13814ac408..4a268bb511 100644 --- a/bika/lims/browser/controlpanel.zcml +++ b/bika/lims/browser/controlpanel.zcml @@ -15,4 +15,12 @@ permission="plone.app.controlpanel.Overview" layer="bika.lims.interfaces.IBikaLIMS"/> + + + diff --git a/bika/lims/browser/css/setupview.css b/bika/lims/browser/css/setupview.css new file mode 100644 index 0000000000..7476dc318c --- /dev/null +++ b/bika/lims/browser/css/setupview.css @@ -0,0 +1,32 @@ +/* CSS Styles for the SENAITE Setup View*/ +.vcenter { + display: inline-block; + vertical-align: middle; + float: none; +} +.tile { + width: 100%; + height: 6em; + box-sizing: border-box; + display: inline-block; + background: #d9edf7; + padding: 2em; + margin: auto auto 1em auto; + overflow: hidden; +} +.tile .title { + text-transform: uppercase; + font-weight: bold; + text-overflow: ellipsis; + overflow: hidden; +} +.tile:hover { + background: #d9edff; + text-decoration: none; +} +.tile.setup { + background: #ddd; +} +.tile.setup:hover { + background: #aaa; +} diff --git a/bika/lims/browser/images/gears.png b/bika/lims/browser/images/gears.png new file mode 100644 index 0000000000..16ad2104cf Binary files /dev/null and b/bika/lims/browser/images/gears.png differ diff --git a/bika/lims/browser/templates/setupview.pt b/bika/lims/browser/templates/setupview.pt new file mode 100644 index 0000000000..0b0ea18451 --- /dev/null +++ b/bika/lims/browser/templates/setupview.pt @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/bika/lims/browser/viewlets/configure.zcml b/bika/lims/browser/viewlets/configure.zcml index 7b4dd5bcec..ff869b7619 100644 --- a/bika/lims/browser/viewlets/configure.zcml +++ b/bika/lims/browser/viewlets/configure.zcml @@ -2,6 +2,15 @@ xmlns:browser="http://namespaces.zope.org/browser" i18n_domain="senaite.core"> + + + +
+ + + + + + + +