Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Fine-grained visibility of analyses in results reports and client views #241

Merged
merged 2 commits into from
Sep 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 37 additions & 1 deletion bika/lims/browser/analyses.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from bika.lims.browser.bika_listing import BikaListingView
from bika.lims.config import QCANALYSIS_TYPES
from bika.lims.interfaces import IResultOutOfRange
from bika.lims.interfaces import IRoutineAnalysis
from bika.lims.permissions import *
from bika.lims.permissions import Verify as VerifyPermission
from bika.lims.utils import isActive
Expand Down Expand Up @@ -137,6 +138,12 @@ def __init__(self, context, request, **kwargs):
'title': _('Due Date'),
'index': 'getDueDate',
'sortable': False},
'Hidden': {
'title': _('Hidden'),
'toggle': True,
'sortable': False,
'input_class': 'autosave',
'type': 'boolean'},
}

self.review_states = [
Expand All @@ -154,7 +161,8 @@ def __init__(self, context, request, **kwargs):
'Uncertainty',
'CaptureDate',
'DueDate',
'state_title']
'state_title',
'Hidden']
},
]
if not context.bika_setup.getShowPartitions():
Expand Down Expand Up @@ -914,6 +922,23 @@ def folderitem(self, obj, item, index):
t(_('It comes form a reflex rule'))
))
item['after']['Service'] = ' '.join(after_icons)


# Users that can Add Analyses to an Analysis Request must be able to
# set the visibility of the analysis in results report, also if the
# current state of the Analysis Request (e.g. verified) does not allow
# the edition of other fields. Note that an analyst has no privileges
# by default to edit this value, cause this "visibility" field is
# related with results reporting and/or visibility from the client side.
# This behavior only applies to routine analyses, the visibility of QC
# analyses is managed in publish and are not visible to clients.
if 'Hidden' in self.columns:
# TODO Performance. Use brain instead
full_obj = full_obj if full_obj else obj.getObject()
item['Hidden'] = full_obj.getHidden()
if IRoutineAnalysis.providedBy(full_obj):
item['allow_edit'].append('Hidden')

return item

def folderitems(self):
Expand Down Expand Up @@ -944,6 +969,17 @@ def folderitems(self):
self.allow_edit = can_edit_analyses
self.show_select_column = self.allow_edit

# Users that can Add Analyses to an Analysis Request must be able to
# set the visibility of the analysis in results report, also if the
# current state of the Analysis Request (e.g. verified) does not allow
# the edition of other fields. Note that an analyst has no privileges
# by default to edit this value, cause this "visibility" field is
# related with results reporting and/or visibility from the client side.
# This behavior only applies to routine analyses, the visibility of QC
# analyses is managed in publish and are not visible to clients.
if not self.mtool.checkPermission(AddAnalysis, self.context):
self.remove_column('Hidden')

self.categories = []
# Getting the multi-verification type of bika_setup
self.mv_type = self.context.bika_setup.getTypeOfmultiVerification()
Expand Down
7 changes: 2 additions & 5 deletions bika/lims/browser/analysisrequest/publish.py
Original file line number Diff line number Diff line change
Expand Up @@ -1189,11 +1189,8 @@ def _analyses_data(self, ar, analysis_states=None):
full_objects=True, review_state=analysis_states):

# Omit hidden analyses?
if not showhidden:
asets = ar.getAnalysisServiceSettings(an.getServiceUID())
if asets.get('hidden'):
# Hide analysis
continue
if not showhidden and an.getHidden():
continue

# Build the analysis-specific dict
andict = self._analysis_data(an, dm)
Expand Down
8 changes: 8 additions & 0 deletions bika/lims/browser/bika_listing.py
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,14 @@ def before_render(self):
"""
pass

def remove_column(self, column):
"""Removes the column passed-in, if exists"""
if column in self.columns:
del self.columns[column]
for item in self.review_states:
if column in item.get('columns', []):
item['columns'].remove(column)

def __call__(self):
""" Handle request parameters and render the form."""

Expand Down
14 changes: 8 additions & 6 deletions bika/lims/browser/js/bika.lims.bikalisting.js
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,9 @@ function BikaListingTableView() {
*/
var fieldvalue, fieldname, requestdata={}, uid, tr;
fieldvalue = $(pointer).val();
if ($(pointer).is(':checkbox')) {
fieldvalue = $(pointer).is(':checked');
}
fieldname = $(pointer).attr('field');
tr = $(pointer).closest('tr');
uid = $(pointer).attr('uid');
Expand All @@ -689,7 +692,6 @@ function BikaListingTableView() {
var url = window.location.href.replace('/base_view', '');
// Staff for the notification
var name = $(tr).attr('title');
var anch = "<a href='"+ url + "'>" + name + "</a>";
$.ajax({
type: "POST",
url: window.portal_url+"/@@API/update",
Expand All @@ -698,18 +700,18 @@ function BikaListingTableView() {
.done(function(data) {
//success alert
if (data != null && data['success'] == true) {
bika.lims.SiteView.notificationPanel(anch + ': ' + name + ' updated successfully', "succeed");
bika.lims.SiteView.notificationPanel(name + ' updated successfully', "succeed");
} else {
bika.lims.SiteView.notificationPanel('Error while updating ' + name + ' for '+ anch, "error");
var msg = '[bika.lims.analysisrequest.js] Error while updating ' + name + ' for '+ ar;
bika.lims.SiteView.notificationPanel('Error while updating ' + name, "error");
var msg = 'Error while updating ' + name;
console.warn(msg);
window.bika.lims.error(msg);
}
})
.fail(function(){
//error
bika.lims.SiteView.notificationPanel('Error while updating ' + name + ' for '+ anch, "error");
var msg = '[bika.lims.analysisrequest.js] Error while updating ' + name + ' for '+ ar;
bika.lims.SiteView.notificationPanel('Error while updating ' + name, "error");
var msg = 'Error while updating ' + name;
console.warn(msg);
window.bika.lims.error(msg);
});
Expand Down
50 changes: 50 additions & 0 deletions bika/lims/content/abstractroutineanalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,16 @@
label=_("Uncertainty")
)
)
# This field keep track if the field hidden has been set manually or not. If
# this value is false, the system will assume the visibility of this analysis
# in results report will depend on the value set at AR, Profile or Template
# levels (see AnalysisServiceSettings fields in AR). If the value for this
# field is set to true, the system will assume the visibility of the analysis
# will only depend on the value set for the field Hidden (bool).
HiddenManually = BooleanField(
'HiddenManually',
default=False,
)

schema = schema.copy() + Schema((
IsReflexAnalysis,
Expand All @@ -98,6 +108,7 @@
ReflexRuleLocalID,
SamplePartition,
Uncertainty,
HiddenManually,
))


Expand Down Expand Up @@ -424,6 +435,45 @@ def getPrioritySortkey(self):
if analysis_request:
return analysis_request.getPrioritySortkey()

@security.public
def getHidden(self):
""" Returns whether if the analysis must be displayed in results
reports or not, as well as in analyses view when the user logged in
is a Client Contact.

If the value for the field HiddenManually is set to False, this function
will delegate the action to the method getAnalysisServiceSettings() from
the Analysis Request.

If the value for the field HiddenManually is set to True, this function
will return the value of the field Hidden.
:return: true or false
:rtype: bool
"""
if self.getHiddenManually():
return self.getField('Hidden').get(self)
request = self.getRequest()
if request:
service_uid = self.getServiceUID()
ar_settings = request.getAnalysisServiceSettings(service_uid)
return ar_settings.get('hidden', False)
return False

@security.public
def setHidden(self, hidden):
""" Sets if this analysis must be displayed or not in results report and
in manage analyses view if the user is a lab contact as well.

The value set by using this field will have priority over the visibility
criteria set at Analysis Request, Template or Profile levels (see
field AnalysisServiceSettings from Analysis Request. To achieve this
behavior, this setter also sets the value to HiddenManually to true.
:param hidden: true if the analysis must be hidden in report
:type hidden: bool
"""
self.setHiddenManually(True)
self.getField('Hidden').set(self, hidden)

@security.public
def setReflexAnalysisOf(self, analysis):
"""Sets the analysis that has been reflexed in order to create this
Expand Down
10 changes: 6 additions & 4 deletions bika/lims/skins/bika/ploneCustom.css.dtml
Original file line number Diff line number Diff line change
Expand Up @@ -1031,11 +1031,13 @@ h2 a.add-button {
padding: 5px 20px 20px 70px;
}
div#viewlet-above-content-title #panel-notification {
left: 0;
margin: 100px;
padding: 0 280px;
position: absolute;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: 1000;
border: 1px solid #efefef;
box-shadow: 1px 1px 10px #fff;
}
div#viewlet-above-content-title #panel-notification div.error-notification-item {
background: url("/Plone/++resource++bika.lims.images/warning.png") no-repeat scroll 15px center #fff680;
Expand Down
2 changes: 1 addition & 1 deletion bika/lims/utils/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def copy_analysis_field_values(source, analysis, **kwargs):
'creators', 'effectiveDate', 'expirationDate', 'language', 'rights',
'creation_date', 'modification_date', 'IsReflexAnalysis',
'OriginalReflexedAnalysis', 'ReflexAnalysisOf', 'ReflexRuleAction',
'ReflexRuleLocalID', 'ReflexRuleActionsTriggered']
'ReflexRuleLocalID', 'ReflexRuleActionsTriggered', 'Hidden']
for field in src_schema.fields():
fieldname = field.getName()
if fieldname in IGNORE_FIELDNAMES and fieldname not in kwargs:
Expand Down