Passed
Push — 2.x ( 9e4ac8...65b15a )
by Jordi
06:32
created

AttachmentsViewlet.show()   A

Complexity

Conditions 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 8
rs 10
c 0
b 0
f 0
cc 2
nop 1
1
# -*- coding: utf-8 -*-
2
#
3
# This file is part of SENAITE.CORE.
4
#
5
# SENAITE.CORE is free software: you can redistribute it and/or modify it under
6
# the terms of the GNU General Public License as published by the Free Software
7
# Foundation, version 2.
8
#
9
# This program is distributed in the hope that it will be useful, but WITHOUT
10
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12
# details.
13
#
14
# You should have received a copy of the GNU General Public License along with
15
# this program; if not, write to the Free Software Foundation, Inc., 51
16
# Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
#
18
# Copyright 2018-2021 by it's authors.
19
# Some rights reserved, see README and LICENSE.
20
21
from bika.lims import FieldEditAnalysisResult
22
from bika.lims import api
23
from bika.lims.api.security import check_permission
24
from bika.lims.interfaces import IReferenceAnalysis
25
from plone.app.layout.viewlets.common import ViewletBase
26
from plone.memoize import view
27
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
28
from senaite.core.permissions.worksheet import can_add_worksheet_attachment
29
30
31
class AttachmentsViewlet(ViewletBase):
32
    """Viewlet to manage Attachments in ARs
33
34
    Most of the heavy lifting is now delegated in the template to the
35
    `attachments_view` browser view.
36
    """
37
    template = ViewPageTemplateFile("templates/attachments.pt")
38
39
    def toggle_css_class(self):
40
        """CSS toggle class selector to keep attachments viewlet open
41
        """
42
        if self.request.get("show_attachments", False):
43
            return "show"
44
        return "collapse"
45
46
    def get_attachments_view(self):
47
        # refactored functionality into this separate Browser view, to be able
48
        # to have a form submit target.
49
        attachments_view = api.get_view("attachments_view",
50
                                        context=self.context,
51
                                        request=self.request)
52
        return attachments_view
53
54
    def show(self):
55
        """Controls if the viewlet should be rendered
56
        """
57
        url = self.request.getURL()
58
        # XXX: Hack to show the viewlet only on the AR base_view
59
        if not any(map(url.endswith, ["base_view", "manage_results"])):
60
            return False
61
        return True
62
63
    def update(self):
64
        """Called always before render()
65
        """
66
        super(AttachmentsViewlet, self).update()
67
        self.attachments_view = self.get_attachments_view()
68
69
    def render(self):
70
        if not self.show():
71
            return ""
72
        return self.template()
73
74
75
class WorksheetAttachmentsViewlet(AttachmentsViewlet):
76
    """Viewlet to manage Attachments on Worksheets
77
78
    Most of the heavy lifting is now delegated in the template to the
79
    `attachments_view` browser view.
80
    """
81
    template = ViewPageTemplateFile("templates/worksheet_attachments.pt")
82
83
    def show(self):
84
        """Controls if the viewlet should be rendered
85
        """
86
        # XXX: Hack to show the viewlet only on the WS manage_results view
87
        if not self.request.getURL().endswith("manage_results"):
88
            return False
89
        return can_add_worksheet_attachment(self.context)
90
91
    @view.memoize
92
    def get_services(self):
93
        """Returns a list of dicts that represent the Analysis Services that
94
        are editable and present in current Worksheet
95
        """
96
        services = set()
97
        for analysis in self.context.getAnalyses():
98
            # Skip non-editable analyses
99
            if not check_permission(FieldEditAnalysisResult, analysis):
100
                continue
101
            service = analysis.getAnalysisService()
102
            services.add(service)
103
104
        # Return the
105
        services = sorted(list(services), key=lambda s: api.get_title(s))
106
        return map(self.get_service_info, services)
107
108
    def get_service_info(self, service):
109
        """Returns a dict that represents an analysis service
110
        """
111
        return {
112
            "uid": api.get_uid(service),
113
            "title": api.get_title(service),
114
        }
115
116
    @view.memoize
117
    def get_analyses(self):
118
        """Returns a list of dicts that represent the Analyses that are
119
        editable and present in current Worksheet
120
        """
121
        analyses = set()
122
        for analysis in self.context.getAnalyses():
123
            # Skip Reference Analysis
124
            if IReferenceAnalysis.providedBy(analysis):
125
                continue
126
                
127
            # Skip non-editable analyses
128
            if not check_permission(FieldEditAnalysisResult, analysis):
129
                continue
130
            analyses.add(analysis)
131
132
        analyses = map(self.get_analysis_info, analyses)
133
        return sorted(analyses, key=lambda s: s.get("title"))
134
135
    def get_analysis_info(self, analysis):
136
        """Returns a dict that represents an analysis
137
        """
138
        title = api.get_title(analysis)
139
        sample_id = analysis.getRequestID()
140
        position = self.context.get_slot_position_for(analysis)
141
        return {
142
            "uid": api.get_uid(analysis),
143
            "title": "{}: {} - {}".format(str(position), sample_id, title)
144
        }
145