Skip to content

Commit

Permalink
Added ContentSectionViewletManager to allow dynamic addition of secti…
Browse files Browse the repository at this point in the history
…ons (#1690)

* Allow to add new sections in Sample via adapters

* Ensure deepcopy interims

* Use Viewlets approach instead of our own subscriber adapters

* Refactored sample sections viewlets

* Added viewlet render condition

* Sample is the current context

Co-authored-by: Ramon Bartl <rb@ridingbytes.com>
  • Loading branch information
xispa and ramonski authored Dec 3, 2020
1 parent ef38067 commit 34e9fe4
Show file tree
Hide file tree
Showing 10 changed files with 152 additions and 75 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
2.0.0rc3 (unreleased)
---------------------

- #1690 Added ContentSectionViewletManager to allow dynamic addition of sections
- #1698 Apply focus styling for setup view tiles when tabbing
- #1696 Fix interims with choices are not displayed in listings after a while
- #1695 Fix form submission for required multi-reference fields
Expand Down
1 change: 0 additions & 1 deletion src/bika/lims/browser/analysisrequest/tables.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
# Some rights reserved, see README and LICENSE.

from bika.lims import api
from bika.lims import bikaMessageFactory as _
from bika.lims.browser.analyses.qc import QCAnalysesView
from bika.lims.browser.analyses.view import AnalysesView

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,47 +70,12 @@
</div>
<!-- /Remarks Widget -->

<tal:field_analyses condition="python:view.has_field_analyses()">
<div class="row">
<div class="col-sm-12">
<h3>
<i class="fieldanalyses-icon" title="Field Analyses" i18n:attributes="title">
<svg tal:replace="structure senaite_theme/icon_data/analysisservice" />
</i>
<span i18n:translate="">Field Analyses</span>
</h3>
<span tal:replace="structure python:view.render_analyses_table(table='field')"/>
</div>
</div>
</tal:field_analyses>

<tal:lab_analyses condition="python:view.has_lab_analyses()">
<div class="row">
<div class="col-sm-12">
<h3>
<i class="labanalyses-icon" title="Lab Analyses" i18n:attributes="title">
<svg tal:replace="structure senaite_theme/icon_data/analysisservice" />
</i>
<span i18n:translate="">Lab Analyses</span>
</h3>
<span tal:replace="structure python:view.render_analyses_table(table='lab')"/>
</div>
</div>
</tal:lab_analyses>

<tal:qc_analyses condition="python:view.has_qc_analyses()">
<div class="row">
<div class="col-sm-12">
<h3>
<i class="qcanalyses-icon" title="QC Analyses" i18n:attributes="title">
<svg tal:replace="structure senaite_theme/icon_data/analysisservice" />
</i>
<span i18n:translate="">QC Analyses</span>
</h3>
<span tal:replace="structure python:view.render_analyses_table(table='qc')"/>
</div>
<!-- Viewlet manager for sample sections -->
<div class="row" id="sample-sections">
<div class="col-sm-12">
<div tal:replace="structure provider:senaite.samplesections"></div>
</div>
</tal:qc_analyses>
</div>

<!-- Results interpretation -->
<div class="row">
Expand Down
34 changes: 0 additions & 34 deletions src/bika/lims/browser/analysisrequest/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,40 +47,6 @@ def __call__(self):

return self.template()

def render_analyses_table(self, table="lab"):
"""Render Analyses Table
"""
if table not in ["lab", "field", "qc"]:
raise KeyError("Table '{}' does not exist".format(table))
view_name = "table_{}_analyses".format(table)
view = api.get_view(
view_name, context=self.context, request=self.request)
# Call listing hooks
view.update()
view.before_render()
return view.ajax_contents_table()

def has_lab_analyses(self):
"""Check if the AR contains lab analyses
"""
# Negative performance impact - add a Metadata column
analyses = self.context.getAnalyses(getPointOfCapture="lab")
return len(analyses) > 0

def has_field_analyses(self):
"""Check if the AR contains field analyses
"""
# Negative performance impact - add a Metadata column
analyses = self.context.getAnalyses(getPointOfCapture="field")
return len(analyses) > 0

def has_qc_analyses(self):
"""Check if the AR contains field analyses
"""
# Negative performance impact - add a Metadata column
analyses = self.context.getQCAnalyses()
return len(analyses) > 0

def is_hazardous(self):
"""Checks if the AR is hazardous
"""
Expand Down
36 changes: 36 additions & 0 deletions src/senaite/core/browser/viewlets/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -227,5 +227,41 @@
layer="senaite.core.interfaces.ISenaiteCore"
/>

<!-- Viewlet manager that sits in the sample view content area -->
<browser:viewletManager
name="senaite.samplesections"
provides=".interfaces.ISampleSection"
class="plone.app.viewletmanager.manager.OrderedViewletManager"
permission="zope2.View"
layer="senaite.core.interfaces.ISenaiteCore"
/>

<!-- Sample section viewlet: lab analyses lisiting -->
<browser:viewlet
for="bika.lims.interfaces.IAnalysisRequest"
name="senaite.core.samplesection.lab_analyses"
manager=".interfaces.ISampleSection"
class=".sampleanalyses.LabAnalysesViewlet"
layer="senaite.core.interfaces.ISenaiteCore"
permission="zope2.View" />


<!-- Sample section viewlet: field analyses lisiting -->
<browser:viewlet
for="bika.lims.interfaces.IAnalysisRequest"
name="senaite.core.samplesection.field_analyses"
manager=".interfaces.ISampleSection"
class=".sampleanalyses.FieldAnalysesViewlet"
layer="senaite.core.interfaces.ISenaiteCore"
permission="zope2.View" />

<!-- Sample section viewlet: QC analyses listing -->
<browser:viewlet
for="bika.lims.interfaces.IAnalysisRequest"
name="senaite.core.samplesection.qc_analyses"
manager=".interfaces.ISampleSection"
class=".sampleanalyses.QCAnalysesViewlet"
layer="senaite.core.interfaces.ISenaiteCore"
permission="zope2.View" />

</configure>
5 changes: 5 additions & 0 deletions src/senaite/core/browser/viewlets/interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,8 @@ class IAboveListingTable(IViewletManager):
class IBelowListingTable(IViewletManager):
"""A viewlet manager that sits below listing tables
"""


class ISampleSection(IViewletManager):
"""A viewlet manager responsible for sample sections below the header table
"""
77 changes: 77 additions & 0 deletions src/senaite/core/browser/viewlets/sampleanalyses.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# -*- 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 api
from bika.lims import senaiteMessageFactory as _
from plone.app.layout.viewlets import ViewletBase
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile


class LabAnalysesViewlet(ViewletBase):
"""Laboratory analyses section viewlet for Sample view
"""
index = ViewPageTemplateFile("templates/sampleanalyses.pt")

title = _("Analyses")
icon_name = "analysisservice"
capture = "lab"

@property
def sample(self):
return self.context

def available(self):
"""Returns true if this sample contains at least one analysis for the
point of capture (capture)
"""
analyses = self.sample.getAnalyses(getPointOfCapture=self.capture)
return len(analyses) > 0

def get_listing_view(self):
request = api.get_request()
view_name = "table_{}_analyses".format(self.capture)
view = api.get_view(view_name, context=self.sample, request=request)
return view

def contents_table(self):
view = self.get_listing_view()
view.update()
view.before_render()
return view.ajax_contents_table()


class FieldAnalysesViewlet(LabAnalysesViewlet):
"""Field analyses section viewlet for Sample view
"""
title = _("Field Analyses")
capture = "field"


class QCAnalysesViewlet(LabAnalysesViewlet):
"""QC analyses section viewlet for Sample view
"""
title = _("QC Analyses")
capture = "qc"

def available(self):
"""Returns true if this sample contains at least one qc analysis
"""
analyses = self.sample.getQCAnalyses()
return len(analyses) > 0
20 changes: 20 additions & 0 deletions src/senaite/core/browser/viewlets/templates/sampleanalyses.pt
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<div class="analysis-listing-table"
tal:condition="python:view.available()"
i18n:domain="senaite.core">
<div class="row mb-4">
<div class="col-sm-12">

<!-- Analysis listing title and icon -->
<h3 tal:define="icon view/icon_name|nothing;
title view/title|nothing"
tal:condition="title">
<img tal:condition="icon|nothing" tal:attributes="src string:senaite_theme/icon/${icon}"/>
<span i18n:translate="" tal:content="title"/>
</h3>

<!-- Analyis listing table -->
<span tal:replace="structure python:view.contents_table()"/>

</div>
</div>
</div>
7 changes: 7 additions & 0 deletions src/senaite/core/profiles/default/viewlets.xml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
<viewlet name="plone.contentviews" />
</order>

<!-- Viewlets in sample sections -->
<order manager="senaite.samplesections" skinname="*">
<viewlet name="senaite.core.samplesection.field_analyses" />
<viewlet name="senaite.core.samplesection.lab_analyses" />
<viewlet name="senaite.core.samplesection.qc_analyses" />
</order>

<!-- Hidden viewlets in plone.portalheader -->
<hidden manager="plone.portalheader" skinname="*" purge="True">
<viewlet name="plone.searchbox"/>
Expand Down
1 change: 1 addition & 0 deletions src/senaite/core/upgrade/v02_00_000.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ def upgrade(tool):
setup.runImportStepFromProfile(profile, "typeinfo")
setup.runImportStepFromProfile(profile, "workflow")
setup.runImportStepFromProfile(profile, "browserlayer")
setup.runImportStepFromProfile(profile, "viewlets")
# run import steps located in bika.lims profiles
_run_import_step(portal, "typeinfo", profile="profile-bika.lims:default")
_run_import_step(portal, "workflow", profile="profile-bika.lims:default")
Expand Down

0 comments on commit 34e9fe4

Please sign in to comment.