esdrt.content 2.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- esdrt/content/INTEGRATION.txt +36 -0
- esdrt/content/__init__.py +5 -0
- esdrt/content/adapters/__init__.py +0 -0
- esdrt/content/adapters/configure.zcml +11 -0
- esdrt/content/adapters/reference_number.py +42 -0
- esdrt/content/browser/__init__.py +1 -0
- esdrt/content/browser/attachmentdownload.py +22 -0
- esdrt/content/browser/carryover.py +247 -0
- esdrt/content/browser/comments.py +22 -0
- esdrt/content/browser/configure.zcml +233 -0
- esdrt/content/browser/copyfiles.py +22 -0
- esdrt/content/browser/get_sample_xls.py +164 -0
- esdrt/content/browser/inbox_sections.py +225 -0
- esdrt/content/browser/interfaces.py +5 -0
- esdrt/content/browser/macros.py +15 -0
- esdrt/content/browser/management.py +97 -0
- esdrt/content/browser/observation_import.py +383 -0
- esdrt/content/browser/statechange.py +529 -0
- esdrt/content/browser/statisticsview.py +495 -0
- esdrt/content/browser/tableau.py +29 -0
- esdrt/content/browser/templates/assign_answerer_form.pt +67 -0
- esdrt/content/browser/templates/assign_conclusion_reviewer_form.pt +72 -0
- esdrt/content/browser/templates/assign_counterpart_form.pt +99 -0
- esdrt/content/browser/templates/carryover.pt +113 -0
- esdrt/content/browser/templates/comments.pt +308 -0
- esdrt/content/browser/templates/finalisedfolderview.pt +595 -0
- esdrt/content/browser/templates/import_observation.pt +28 -0
- esdrt/content/browser/templates/inboxreviewfolderview.pt +155 -0
- esdrt/content/browser/templates/macros.pt +56 -0
- esdrt/content/browser/templates/multi_input.pt +80 -0
- esdrt/content/browser/templates/reviewfolder_get_table.pt +108 -0
- esdrt/content/browser/templates/reviewfolderview.pt +500 -0
- esdrt/content/browser/templates/statisticsview.pt +380 -0
- esdrt/content/browser/templates/tableau_dashboard.pt +35 -0
- esdrt/content/comment.py +184 -0
- esdrt/content/commentanswer.py +131 -0
- esdrt/content/commentextender.py +70 -0
- esdrt/content/conclusion.py +283 -0
- esdrt/content/conclusionsphase2.py +282 -0
- esdrt/content/configure.zcml +92 -0
- esdrt/content/constants.py +56 -0
- esdrt/content/converter.py +41 -0
- esdrt/content/crf_code_matching.py +71 -0
- esdrt/content/esdrtfile.py +88 -0
- esdrt/content/forms.zcml +162 -0
- esdrt/content/indexers.py +428 -0
- esdrt/content/interfaces.py +8 -0
- esdrt/content/ldap_utils.py +44 -0
- esdrt/content/locales/README.txt +2 -0
- esdrt/content/notifications/__init__.py +0 -0
- esdrt/content/notifications/answer_acknowledged.pt +18 -0
- esdrt/content/notifications/answer_acknowledged.py +23 -0
- esdrt/content/notifications/answer_to_msexperts.pt +18 -0
- esdrt/content/notifications/answer_to_msexperts.py +23 -0
- esdrt/content/notifications/conclusion_to_comment.pt +18 -0
- esdrt/content/notifications/conclusion_to_comment.py +60 -0
- esdrt/content/notifications/configure.zcml +7 -0
- esdrt/content/notifications/observation_finalisation_denied.pt +18 -0
- esdrt/content/notifications/observation_finalisation_denied.py +41 -0
- esdrt/content/notifications/observation_finalisation_request.pt +18 -0
- esdrt/content/notifications/observation_finalisation_request.py +40 -0
- esdrt/content/notifications/observation_finalised.pt +18 -0
- esdrt/content/notifications/observation_finalised.py +79 -0
- esdrt/content/notifications/observation_finalised_ms_remarks.pt +18 -0
- esdrt/content/notifications/observation_finalised_rev_msg.pt +18 -0
- esdrt/content/notifications/observation_to_phase2.pt +18 -0
- esdrt/content/notifications/observation_to_phase2.py +40 -0
- esdrt/content/notifications/observation_to_phase2_rev_msg.pt +18 -0
- esdrt/content/notifications/question_answered.py +98 -0
- esdrt/content/notifications/question_answered_lr_msg.pt +18 -0
- esdrt/content/notifications/question_answered_msexperts_msg.pt +18 -0
- esdrt/content/notifications/question_answered_rev_msg.pt +18 -0
- esdrt/content/notifications/question_ready_for_approval.pt +18 -0
- esdrt/content/notifications/question_ready_for_approval.py +41 -0
- esdrt/content/notifications/question_to_counterpart.pt +18 -0
- esdrt/content/notifications/question_to_counterpart.py +60 -0
- esdrt/content/notifications/question_to_ms.pt +18 -0
- esdrt/content/notifications/question_to_ms.py +88 -0
- esdrt/content/notifications/question_to_ms_rev_msg.pt +18 -0
- esdrt/content/notifications/utils.py +159 -0
- esdrt/content/observation.py +2358 -0
- esdrt/content/overrides.zcml +17 -0
- esdrt/content/patches.py +64 -0
- esdrt/content/patches.zcml +34 -0
- esdrt/content/permissions.zcml +90 -0
- esdrt/content/profiles/default/browserlayer.xml +7 -0
- esdrt/content/profiles/default/catalog.xml +155 -0
- esdrt/content/profiles/default/diff_tool.xml +43 -0
- esdrt/content/profiles/default/ldapsettings.xml +60 -0
- esdrt/content/profiles/default/metadata.xml +10 -0
- esdrt/content/profiles/default/registry/generic.xml +129 -0
- esdrt/content/profiles/default/registry/plone.xml +21 -0
- esdrt/content/profiles/default/registry/resources.xml +53 -0
- esdrt/content/profiles/default/rolemap.xml +88 -0
- esdrt/content/profiles/default/sharing.xml +85 -0
- esdrt/content/profiles/default/tinymce.xml +14 -0
- esdrt/content/profiles/default/types/Comment.xml +57 -0
- esdrt/content/profiles/default/types/CommentAnswer.xml +57 -0
- esdrt/content/profiles/default/types/Conclusion.xml +59 -0
- esdrt/content/profiles/default/types/ConclusionsPhase2.xml +59 -0
- esdrt/content/profiles/default/types/ESDRTFile.xml +57 -0
- esdrt/content/profiles/default/types/Folder.xml +6 -0
- esdrt/content/profiles/default/types/Observation.xml +61 -0
- esdrt/content/profiles/default/types/Question.xml +60 -0
- esdrt/content/profiles/default/types/ReviewFolder.xml +60 -0
- esdrt/content/profiles/default/types.xml +20 -0
- esdrt/content/profiles/default/workflows/esd-answer-workflow/definition.xml +177 -0
- esdrt/content/profiles/default/workflows/esd-comment-workflow/definition.xml +170 -0
- esdrt/content/profiles/default/workflows/esd-conclusion-phase2-workflow/definition.xml +320 -0
- esdrt/content/profiles/default/workflows/esd-conclusion-workflow/definition.xml +324 -0
- esdrt/content/profiles/default/workflows/esd-file-workflow/definition.xml +180 -0
- esdrt/content/profiles/default/workflows/esd-question-review-workflow/definition.xml +1654 -0
- esdrt/content/profiles/default/workflows/esd-review-workflow/definition.xml +1054 -0
- esdrt/content/profiles/default/workflows/esd-reviewtool-folder-workflow/definition.xml +350 -0
- esdrt/content/profiles/default/workflows.xml +41 -0
- esdrt/content/profiles/uninstall/browserlayer.xml +7 -0
- esdrt/content/profiles.zcml +30 -0
- esdrt/content/question.py +538 -0
- esdrt/content/reviewfolder.py +1934 -0
- esdrt/content/roles/__init__.py +0 -0
- esdrt/content/roles/configure.zcml +38 -0
- esdrt/content/roles/localroles.py +301 -0
- esdrt/content/roles/localrolesubscriber.py +52 -0
- esdrt/content/setuphandlers.py +86 -0
- esdrt/content/static/chosen-sprite.png +0 -0
- esdrt/content/static/chosen-sprite@2x.png +0 -0
- esdrt/content/static/chosen.jquery.js +1211 -0
- esdrt/content/static/chosen.min.css +3 -0
- esdrt/content/static/cookies.js +77 -0
- esdrt/content/static/eea-tabs.css +108 -0
- esdrt/content/static/eea-tabs.js +27 -0
- esdrt/content/static/esdrt.content.css +760 -0
- esdrt/content/static/flags.css +52 -0
- esdrt/content/static/flags.png +0 -0
- esdrt/content/static/icons/bootstrap-icons.min.css +5 -0
- esdrt/content/static/icons/fonts/bootstrap-icons.woff +0 -0
- esdrt/content/static/icons/fonts/bootstrap-icons.woff2 +0 -0
- esdrt/content/static/inbox_view.css +49 -0
- esdrt/content/static/inbox_view.js +50 -0
- esdrt/content/static/moment.min.js +6 -0
- esdrt/content/static/phase-1.png +0 -0
- esdrt/content/static/phase-12.png +0 -0
- esdrt/content/static/phase-2.png +0 -0
- esdrt/content/subscribers.py +310 -0
- esdrt/content/subscribers.zcml +283 -0
- esdrt/content/subscriptionconfiguration.py +251 -0
- esdrt/content/subscriptions/__init__.py +1 -0
- esdrt/content/subscriptions/configure.zcml +24 -0
- esdrt/content/subscriptions/dexterity.py +70 -0
- esdrt/content/subscriptions/interfaces.py +42 -0
- esdrt/content/templates/diffedview.pt +519 -0
- esdrt/content/templates/observationview.pt +1399 -0
- esdrt/content/templates/subscriptionconfiguration.pt +243 -0
- esdrt/content/templates/subscriptionconfigurationreview.pt +120 -0
- esdrt/content/tests.py +62 -0
- esdrt/content/timeit.py +47 -0
- esdrt/content/upgrades/__init__.py +0 -0
- esdrt/content/upgrades/configure.zcml +59 -0
- esdrt/content/upgrades/evolve_2002.py +10 -0
- esdrt/content/upgrades/evolve_2003.py +10 -0
- esdrt/content/upgrades/portal_workflow.py +119 -0
- esdrt/content/upgrades/reindex_observations.py +31 -0
- esdrt/content/upgrades/templates/portal_workflow_apply_and_reindex.pt +101 -0
- esdrt/content/utilities/__init__.py +1 -0
- esdrt/content/utilities/configure.zcml +22 -0
- esdrt/content/utilities/interfaces.py +36 -0
- esdrt/content/utilities/ldap_utils.py +177 -0
- esdrt/content/utilities/ms_user.py +18 -0
- esdrt/content/utilities/question.py +45 -0
- esdrt/content/utilities/roles.py +73 -0
- esdrt/content/utils.py +102 -0
- esdrt/content/views.zcml +237 -0
- esdrt/content/vocabularies/__init__.py +0 -0
- esdrt/content/vocabularies/configure.zcml +70 -0
- esdrt/content/vocabularies/data/conclusion_phase2_reasons.csv +3 -0
- esdrt/content/vocabularies/data/conclusion_reasons.csv +3 -0
- esdrt/content/vocabularies/data/crf_code.csv +115 -0
- esdrt/content/vocabularies/data/eea_member_states.csv +39 -0
- esdrt/content/vocabularies/data/fuel.csv +6 -0
- esdrt/content/vocabularies/data/gas.csv +7 -0
- esdrt/content/vocabularies/data/ghg_source_category.csv +13 -0
- esdrt/content/vocabularies/data/ghg_source_sectors.csv +6 -0
- esdrt/content/vocabularies/data/highlight.csv +19 -0
- esdrt/content/vocabularies/data/parameter.csv +11 -0
- esdrt/content/vocabularies/interfaces.py +68 -0
- esdrt/content/vocabularies/vocabularies.py +246 -0
- esdrt.content-2.0.3-py3.14-nspkg.pth +1 -0
- esdrt_content-2.0.3.dist-info/METADATA +1319 -0
- esdrt_content-2.0.3.dist-info/RECORD +193 -0
- esdrt_content-2.0.3.dist-info/WHEEL +5 -0
- esdrt_content-2.0.3.dist-info/entry_points.txt +2 -0
- esdrt_content-2.0.3.dist-info/namespace_packages.txt +1 -0
- esdrt_content-2.0.3.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
Integration Tests
|
|
2
|
+
-----------------
|
|
3
|
+
|
|
4
|
+
This is a DocTest file, using the Python doctest format.
|
|
5
|
+
|
|
6
|
+
In an integration test, here's some of the globals you have to work with::
|
|
7
|
+
|
|
8
|
+
>>> portal
|
|
9
|
+
<PloneSite at /plone>
|
|
10
|
+
|
|
11
|
+
>>> portal_name
|
|
12
|
+
'plone'
|
|
13
|
+
|
|
14
|
+
>>> folder
|
|
15
|
+
<ATFolder at /plone/Members/test_user_1_>
|
|
16
|
+
|
|
17
|
+
>>> user_name
|
|
18
|
+
'test_user_1_'
|
|
19
|
+
|
|
20
|
+
>>> user_password
|
|
21
|
+
'secret'
|
|
22
|
+
|
|
23
|
+
>>> user_role
|
|
24
|
+
'test_role_1_'
|
|
25
|
+
|
|
26
|
+
>>> app.REQUEST
|
|
27
|
+
<HTTPRequest, URL=http://nohost>
|
|
28
|
+
|
|
29
|
+
>>> app
|
|
30
|
+
<Application at >
|
|
31
|
+
|
|
32
|
+
Now, let's demonstrate a failing test::
|
|
33
|
+
|
|
34
|
+
>>> 1 == 2
|
|
35
|
+
True
|
|
36
|
+
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<configure
|
|
2
|
+
xmlns="http://namespaces.zope.org/zope"
|
|
3
|
+
xmlns:plone="http://namespaces.plone.org/plone">
|
|
4
|
+
|
|
5
|
+
<adapter
|
|
6
|
+
for="esdrt.content.reviewfolder.IReviewFolder"
|
|
7
|
+
provides="zope.container.interfaces.INameChooser"
|
|
8
|
+
factory=".reference_number.ReferenceNumberCreator"
|
|
9
|
+
/>
|
|
10
|
+
|
|
11
|
+
</configure>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from zope.component import adapter
|
|
2
|
+
from zope.interface import implementer
|
|
3
|
+
|
|
4
|
+
from esdrt.content.observation import IObservation
|
|
5
|
+
from plone.app.content.interfaces import INameFromTitle
|
|
6
|
+
from plone.app.content.namechooser import NormalizingNameChooser
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
ATTEMPTS = 100
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class INameFromData(INameFromTitle):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
@adapter(IObservation)
|
|
16
|
+
@implementer(INameFromData)
|
|
17
|
+
class ReferenceNumberCreator(NormalizingNameChooser):
|
|
18
|
+
"""A name chooser for a Zope object manager.
|
|
19
|
+
|
|
20
|
+
If the object is adaptable to or provides INameFromTitle, use the
|
|
21
|
+
title to generate a name.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def chooseName(self, name, object):
|
|
25
|
+
parent = self.context
|
|
26
|
+
items = []
|
|
27
|
+
items.append(object.country.upper())
|
|
28
|
+
items.append(object.crf_code)
|
|
29
|
+
items.append(str(object.review_year))
|
|
30
|
+
prename = '-'.join(items)
|
|
31
|
+
number = 1
|
|
32
|
+
observations = [k for k in list(parent.keys()) if k.startswith(prename)]
|
|
33
|
+
if observations:
|
|
34
|
+
observations.sort()
|
|
35
|
+
last_observation = observations[-1]
|
|
36
|
+
number = int(last_observation.split('-')[-1])
|
|
37
|
+
number = number + 1
|
|
38
|
+
last_part = '%04d' % number
|
|
39
|
+
name = prename + '-' + last_part
|
|
40
|
+
|
|
41
|
+
# OFS.ObjectManager.checkValidId fails unless the id is str
|
|
42
|
+
return str(name)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from plone.namedfile.browser import Download as Base
|
|
2
|
+
from plone.rfc822.interfaces import IPrimaryFieldInfo
|
|
3
|
+
from zope.publisher.interfaces import NotFound
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Download(Base):
|
|
7
|
+
def _getFile(self):
|
|
8
|
+
if not self.fieldname:
|
|
9
|
+
info = IPrimaryFieldInfo(self.context, None)
|
|
10
|
+
if info is None:
|
|
11
|
+
# Ensure that we have at least a filedname
|
|
12
|
+
raise NotFound(self, '', self.request)
|
|
13
|
+
self.fieldname = info.fieldname
|
|
14
|
+
file = info.value
|
|
15
|
+
else:
|
|
16
|
+
context = getattr(self.context, 'aq_explicit', self.context)
|
|
17
|
+
file = getattr(context, self.fieldname, None)
|
|
18
|
+
|
|
19
|
+
if file is None:
|
|
20
|
+
raise NotFound(self, self.fieldname, self.request)
|
|
21
|
+
|
|
22
|
+
return file
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
from functools import partial
|
|
2
|
+
from itertools import takewhile
|
|
3
|
+
from logging import getLogger
|
|
4
|
+
|
|
5
|
+
import openpyxl
|
|
6
|
+
import plone.api as api
|
|
7
|
+
from DateTime import DateTime
|
|
8
|
+
from Products.CMFCore.utils import getToolByName
|
|
9
|
+
from Products.Five.browser import BrowserView
|
|
10
|
+
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
|
11
|
+
from Products.statusmessages.interfaces import IStatusMessage
|
|
12
|
+
from zope.component.hooks import getSite
|
|
13
|
+
|
|
14
|
+
from esdrt.content.roles.localrolesubscriber import grant_local_roles
|
|
15
|
+
|
|
16
|
+
LOG = getLogger("esdrt.content.carryover")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _read_col(row, nr):
|
|
20
|
+
val = row[nr].value
|
|
21
|
+
return val.strip() if val else val
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _clear_local_roles(obj):
|
|
25
|
+
obj.__ac_local_roles__ = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def clear_and_grant_roles(obj):
|
|
29
|
+
"""Clear any local roles already granted and grant just those
|
|
30
|
+
that make sense in the current review folder context.
|
|
31
|
+
|
|
32
|
+
[refs #105604] This makes sure that users that were granted
|
|
33
|
+
local roles on the old observation will not continue to
|
|
34
|
+
have them (e.g. CounterPart).
|
|
35
|
+
"""
|
|
36
|
+
_clear_local_roles(obj)
|
|
37
|
+
grant_local_roles(obj)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _copy_obj(target, ob, new_id=None):
|
|
41
|
+
orig_ob = ob
|
|
42
|
+
ob_id = new_id or orig_ob.getId()
|
|
43
|
+
ob = ob._getCopy(target)
|
|
44
|
+
ob._setId(ob_id)
|
|
45
|
+
target._setObject(ob_id, ob, suppress_events=True)
|
|
46
|
+
return target[ob_id]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _copy_and_flag(context, obj, new_id=None):
|
|
50
|
+
_, _, year, index = (new_id or obj.getId()).split("-")
|
|
51
|
+
ob = _copy_obj(context, obj, new_id=new_id)
|
|
52
|
+
ob.carryover_from = year
|
|
53
|
+
ob.review_year = int(year)
|
|
54
|
+
|
|
55
|
+
LOG.info(
|
|
56
|
+
"Copied %s -> %s",
|
|
57
|
+
obj.absolute_url(1),
|
|
58
|
+
ob.absolute_url(1),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return ob
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def _obj_from_url(context, site_url, url):
|
|
65
|
+
traversable = str(url.split(site_url)[-1][1:])
|
|
66
|
+
return context.unrestrictedTraverse(traversable)
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def replace_conclusion_text(workflows, obj, text):
|
|
70
|
+
wft = workflows["tool"]
|
|
71
|
+
in_phase2 = wft.getInfoFor(obj, "review_state").startswith("phase2")
|
|
72
|
+
conclusion = obj.get_conclusion_phase2() if in_phase2 else obj.get_conclusion()
|
|
73
|
+
if text and conclusion:
|
|
74
|
+
conclusion.text = text
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def prepend_qa(target, source):
|
|
78
|
+
source_qa = source.get_question()
|
|
79
|
+
target_qa = target.get_question()
|
|
80
|
+
|
|
81
|
+
if source_qa and target_qa:
|
|
82
|
+
for comment in list(source_qa.values()):
|
|
83
|
+
_copy_obj(target_qa, comment)
|
|
84
|
+
|
|
85
|
+
ordering = target_qa.getOrdering()
|
|
86
|
+
ordering.orderObjects(key="creation_date")
|
|
87
|
+
|
|
88
|
+
elif source_qa and not target_qa:
|
|
89
|
+
_copy_obj(target, source_qa)
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def add_to_wh(wf, obj, action, state, actor):
|
|
93
|
+
wh = obj.workflow_history
|
|
94
|
+
wf_id = wf.getId()
|
|
95
|
+
wh[wf_id] = tuple(wh[wf_id]) + (
|
|
96
|
+
{
|
|
97
|
+
"comments": "Carryover force state",
|
|
98
|
+
"actor": actor,
|
|
99
|
+
"time": DateTime(),
|
|
100
|
+
"action": action,
|
|
101
|
+
"review_state": state,
|
|
102
|
+
},
|
|
103
|
+
)
|
|
104
|
+
wf.updateRoleMappingsFor(obj)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def reopen_with_qa(workflows, obj, actor):
|
|
108
|
+
wft = workflows["tool"]
|
|
109
|
+
in_phase2 = wft.getInfoFor(obj, "review_state").startswith("phase2")
|
|
110
|
+
|
|
111
|
+
action_obj = "phase1-reopen"
|
|
112
|
+
action_question = "phase1-reopen"
|
|
113
|
+
new_state_obj = "phase1-carried-over"
|
|
114
|
+
new_state_question = "phase1-draft"
|
|
115
|
+
|
|
116
|
+
add_to_wh(workflows["observation"], obj, action_obj, new_state_obj, actor)
|
|
117
|
+
question = obj.get_question()
|
|
118
|
+
if question:
|
|
119
|
+
add_to_wh(
|
|
120
|
+
workflows["question"],
|
|
121
|
+
question,
|
|
122
|
+
action_question,
|
|
123
|
+
new_state_question,
|
|
124
|
+
actor,
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
if in_phase2:
|
|
128
|
+
wf_conclusion = workflows["conclusion2"]
|
|
129
|
+
conclusion = obj.get_conclusion_phase2()
|
|
130
|
+
else:
|
|
131
|
+
wf_conclusion = workflows["conclusion"]
|
|
132
|
+
conclusion = obj.get_conclusion()
|
|
133
|
+
|
|
134
|
+
if conclusion:
|
|
135
|
+
add_to_wh(wf_conclusion, conclusion, "redraft", "draft", actor)
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def override_owner(obj, owner):
|
|
139
|
+
if owner:
|
|
140
|
+
user = api.portal.get_tool("acl_users").getUserById(owner)
|
|
141
|
+
if user:
|
|
142
|
+
userid = user.getId()
|
|
143
|
+
obj.changeOwnership(user)
|
|
144
|
+
obj.setCreators([userid])
|
|
145
|
+
obj.manage_setLocalRoles(
|
|
146
|
+
userid,
|
|
147
|
+
[
|
|
148
|
+
"Owner",
|
|
149
|
+
],
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def catalog_with_children(catalog, obj):
|
|
154
|
+
catalog.catalog_object(obj)
|
|
155
|
+
for child in obj.objectValues():
|
|
156
|
+
catalog_with_children(catalog, child)
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def copy_direct(context, catalog, workflows, obj_from_url, row):
|
|
160
|
+
source = _read_col(row, 0)
|
|
161
|
+
conclusion_text = _read_col(row, 1)
|
|
162
|
+
actor = _read_col(row, 2)
|
|
163
|
+
owner = _read_col(row, 3)
|
|
164
|
+
|
|
165
|
+
obj = obj_from_url(source)
|
|
166
|
+
ob = _copy_and_flag(context, obj)
|
|
167
|
+
override_owner(ob, owner)
|
|
168
|
+
|
|
169
|
+
replace_conclusion_text(workflows, ob, conclusion_text)
|
|
170
|
+
clear_and_grant_roles(ob)
|
|
171
|
+
reopen_with_qa(workflows, ob, actor, has_step2=context.enable_steps)
|
|
172
|
+
|
|
173
|
+
catalog_with_children(catalog, ob)
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
def copy_complex(context, catalog, workflows, obj_from_url, row):
|
|
177
|
+
source = _read_col(row, 0)
|
|
178
|
+
older_source = _read_col(row, 1)
|
|
179
|
+
conclusion_text = _read_col(row, 2)
|
|
180
|
+
actor = _read_col(row, 3)
|
|
181
|
+
owner = _read_col(row, 4)
|
|
182
|
+
|
|
183
|
+
obj = obj_from_url(source)
|
|
184
|
+
older_obj = obj_from_url(older_source)
|
|
185
|
+
|
|
186
|
+
ob = _copy_and_flag(context, obj, older_obj.getId())
|
|
187
|
+
override_owner(ob, owner)
|
|
188
|
+
|
|
189
|
+
replace_conclusion_text(workflows, ob, conclusion_text)
|
|
190
|
+
prepend_qa(ob, older_obj)
|
|
191
|
+
clear_and_grant_roles(ob)
|
|
192
|
+
reopen_with_qa(workflows, ob, actor, has_step2=context.enable_steps)
|
|
193
|
+
|
|
194
|
+
catalog_with_children(catalog, ob)
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
class CarryOverView(BrowserView):
|
|
198
|
+
index = ViewPageTemplateFile("templates/carryover.pt")
|
|
199
|
+
|
|
200
|
+
def __call__(self):
|
|
201
|
+
return self.index()
|
|
202
|
+
|
|
203
|
+
def start(self, action, xls):
|
|
204
|
+
portal = getSite()
|
|
205
|
+
wb = openpyxl.load_workbook(xls, read_only=True, data_only=True)
|
|
206
|
+
sheet = wb.worksheets[0]
|
|
207
|
+
|
|
208
|
+
sheet_rows = sheet.rows
|
|
209
|
+
next(sheet_rows) # skip first row (header)
|
|
210
|
+
# extract rows with values
|
|
211
|
+
valid_rows = tuple(takewhile(lambda row: any(c.value for c in row), sheet_rows))
|
|
212
|
+
|
|
213
|
+
context = self.context
|
|
214
|
+
site_url = portal.absolute_url()
|
|
215
|
+
obj_from_url = partial(_obj_from_url, context, site_url)
|
|
216
|
+
catalog = getToolByName(portal, "portal_catalog")
|
|
217
|
+
wft = getToolByName(portal, "portal_workflow")
|
|
218
|
+
|
|
219
|
+
wf_obs = wft.getWorkflowById(wft.getChainFor("Observation")[0])
|
|
220
|
+
wf_question = wft.getWorkflowById(wft.getChainFor("Question")[0])
|
|
221
|
+
wf_conclusion = wft.getWorkflowById(wft.getChainFor("Conclusion")[0])
|
|
222
|
+
wf_conclusion2 = wft.getWorkflowById(wft.getChainFor("ConclusionsPhase2")[0])
|
|
223
|
+
|
|
224
|
+
actions = dict(direct=copy_direct, complex=copy_complex)
|
|
225
|
+
workflows = dict(
|
|
226
|
+
tool=wft,
|
|
227
|
+
observation=wf_obs,
|
|
228
|
+
question=wf_question,
|
|
229
|
+
conclusion=wf_conclusion,
|
|
230
|
+
conclusion2=wf_conclusion2,
|
|
231
|
+
)
|
|
232
|
+
copy_func = partial(
|
|
233
|
+
actions[action],
|
|
234
|
+
context,
|
|
235
|
+
catalog,
|
|
236
|
+
workflows,
|
|
237
|
+
obj_from_url,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
for row in valid_rows:
|
|
241
|
+
copy_func(row)
|
|
242
|
+
|
|
243
|
+
if len(valid_rows) > 0:
|
|
244
|
+
(IStatusMessage(self.request).add("Carryover successfull!", type="info"))
|
|
245
|
+
else:
|
|
246
|
+
(IStatusMessage(self.request).add("No data provided!", type="warn"))
|
|
247
|
+
self.request.RESPONSE.redirect(context.absolute_url())
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
|
|
2
|
+
from plone.app.discussion.browser.comments import CommentForm as BaseForm
|
|
3
|
+
from plone.app.discussion.browser.comments import CommentsViewlet as BaseViewlet
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CommentForm(BaseForm):
|
|
7
|
+
|
|
8
|
+
def updateWidgets(self):
|
|
9
|
+
super(CommentForm, self).updateWidgets()
|
|
10
|
+
self.widgets['text'].rows = 15
|
|
11
|
+
|
|
12
|
+
def updateActions(self):
|
|
13
|
+
super(CommentForm, self).updateActions()
|
|
14
|
+
self.actions['comment'].title = 'Save Comment'
|
|
15
|
+
for k in list(self.actions.keys()):
|
|
16
|
+
self.actions[k].addClass('standardButton')
|
|
17
|
+
self.actions[k].addClass('defaultWFButton')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class CommentsViewlet(BaseViewlet):
|
|
21
|
+
index = ViewPageTemplateFile("./templates/comments.pt")
|
|
22
|
+
form = CommentForm
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
<configure
|
|
2
|
+
xmlns="http://namespaces.zope.org/zope"
|
|
3
|
+
xmlns:browser="http://namespaces.zope.org/browser"
|
|
4
|
+
xmlns:i18n="http://namespaces.zope.org/i18n"
|
|
5
|
+
i18n_domain="esdrt.content">
|
|
6
|
+
|
|
7
|
+
<!-- -*- extra stuff goes here -*- -->
|
|
8
|
+
|
|
9
|
+
<browser:page
|
|
10
|
+
name="tableau_dashboard"
|
|
11
|
+
for="..reviewfolder.IReviewFolder"
|
|
12
|
+
class=".tableau.DashboardView"
|
|
13
|
+
permission="zope2.View"
|
|
14
|
+
/>
|
|
15
|
+
|
|
16
|
+
<browser:page
|
|
17
|
+
name="view"
|
|
18
|
+
for="..reviewfolder.IReviewFolder"
|
|
19
|
+
class="..reviewfolder.ReviewFolderView"
|
|
20
|
+
permission="zope2.View"
|
|
21
|
+
template="templates/reviewfolderview.pt"
|
|
22
|
+
/>
|
|
23
|
+
|
|
24
|
+
<browser:page
|
|
25
|
+
name="reindex_context"
|
|
26
|
+
for="*"
|
|
27
|
+
class=".management.ReindexContext"
|
|
28
|
+
permission="cmf.ManagePortal"
|
|
29
|
+
/>
|
|
30
|
+
|
|
31
|
+
<browser:page
|
|
32
|
+
name="fix_carryover_2026"
|
|
33
|
+
for="*"
|
|
34
|
+
class=".management.FixCarryover"
|
|
35
|
+
permission="cmf.ManagePortal"
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
<browser:page
|
|
39
|
+
name="get_table"
|
|
40
|
+
for="..reviewfolder.IReviewFolder"
|
|
41
|
+
class="..reviewfolder.ReviewFolderBrowserView"
|
|
42
|
+
permission="zope2.View"
|
|
43
|
+
attribute="render"
|
|
44
|
+
/>
|
|
45
|
+
|
|
46
|
+
<browser:page
|
|
47
|
+
name="export_as_xls"
|
|
48
|
+
for="..reviewfolder.IReviewFolder"
|
|
49
|
+
class="..reviewfolder.ExportReviewFolderFormView"
|
|
50
|
+
permission="esdrt.content.ExportObservations"
|
|
51
|
+
/>
|
|
52
|
+
|
|
53
|
+
<browser:page
|
|
54
|
+
name="inboxview"
|
|
55
|
+
for="..reviewfolder.IReviewFolder"
|
|
56
|
+
class="..reviewfolder.InboxReviewFolderView"
|
|
57
|
+
permission="zope2.View"
|
|
58
|
+
template="templates/inboxreviewfolderview.pt"
|
|
59
|
+
/>
|
|
60
|
+
|
|
61
|
+
<browser:page
|
|
62
|
+
name="finalisedfolderview"
|
|
63
|
+
for="..reviewfolder.IReviewFolder"
|
|
64
|
+
class="..reviewfolder.FinalisedFolderView"
|
|
65
|
+
permission="zope2.View"
|
|
66
|
+
template="templates/finalisedfolderview.pt"
|
|
67
|
+
/>
|
|
68
|
+
|
|
69
|
+
<browser:page
|
|
70
|
+
name="assign_counterpart_form"
|
|
71
|
+
for="..question.IQuestion"
|
|
72
|
+
class=".statechange.AssignCounterPartForm"
|
|
73
|
+
permission="zope2.View"
|
|
74
|
+
/>
|
|
75
|
+
|
|
76
|
+
<browser:page
|
|
77
|
+
name="reassign_counterpart_form"
|
|
78
|
+
for="..question.IQuestion"
|
|
79
|
+
class=".statechange.ReAssignCounterPartForm"
|
|
80
|
+
permission="zope2.View"
|
|
81
|
+
/>
|
|
82
|
+
|
|
83
|
+
<browser:page
|
|
84
|
+
name="assign_answerer_form"
|
|
85
|
+
for="..question.IQuestion"
|
|
86
|
+
class=".statechange.AssignAnswererForm"
|
|
87
|
+
permission="zope2.View"
|
|
88
|
+
/>
|
|
89
|
+
|
|
90
|
+
<browser:page
|
|
91
|
+
name="select-new-mse"
|
|
92
|
+
for="..question.IQuestion"
|
|
93
|
+
class=".statechange.ReAssignMSExpertsForm"
|
|
94
|
+
permission="zope2.View"
|
|
95
|
+
/>
|
|
96
|
+
|
|
97
|
+
<browser:page
|
|
98
|
+
name="request-redraft"
|
|
99
|
+
for="..question.IQuestion"
|
|
100
|
+
class=".statechange.RequestRedraftReasonForm"
|
|
101
|
+
permission="zope2.View"
|
|
102
|
+
/>
|
|
103
|
+
|
|
104
|
+
<browser:page
|
|
105
|
+
name="assign_conclusion_reviewer_form"
|
|
106
|
+
for="..observation.IObservation"
|
|
107
|
+
class=".statechange.AssignConclusionReviewerForm"
|
|
108
|
+
permission="zope2.View"
|
|
109
|
+
/>
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
<browser:page
|
|
113
|
+
name="request-finish-observation"
|
|
114
|
+
for="..observation.IObservation"
|
|
115
|
+
class=".statechange.FinishObservationReasonForm"
|
|
116
|
+
permission="zope2.View"
|
|
117
|
+
/>
|
|
118
|
+
|
|
119
|
+
<browser:page
|
|
120
|
+
name="deny-finish-observation"
|
|
121
|
+
for="..observation.IObservation"
|
|
122
|
+
class=".statechange.DenyFinishObservationReasonForm"
|
|
123
|
+
permission="zope2.View"
|
|
124
|
+
/>
|
|
125
|
+
|
|
126
|
+
<browser:viewletManager
|
|
127
|
+
name="esdrt.content.commentmanager"
|
|
128
|
+
provides=".interfaces.ICommentDiscussion"
|
|
129
|
+
permission="zope2.View"
|
|
130
|
+
class="plone.app.viewletmanager.manager.BaseOrderedViewletManager"
|
|
131
|
+
/>
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
<browser:viewlet
|
|
135
|
+
name="plone.comments"
|
|
136
|
+
for="..comment.IComment"
|
|
137
|
+
layer="plone.app.discussion.interfaces.IDiscussionLayer"
|
|
138
|
+
manager=".interfaces.ICommentDiscussion"
|
|
139
|
+
view="plone.app.layout.globals.interfaces.IViewView"
|
|
140
|
+
class=".comments.CommentsViewlet"
|
|
141
|
+
permission="esdrt.content.ViewCommentDiscussion"
|
|
142
|
+
/>
|
|
143
|
+
|
|
144
|
+
<browser:viewlet
|
|
145
|
+
name="plone.comments"
|
|
146
|
+
for="..commentanswer.ICommentAnswer"
|
|
147
|
+
layer="plone.app.discussion.interfaces.IDiscussionLayer"
|
|
148
|
+
manager=".interfaces.ICommentDiscussion"
|
|
149
|
+
view="plone.app.layout.globals.interfaces.IViewView"
|
|
150
|
+
class=".comments.CommentsViewlet"
|
|
151
|
+
permission="esdrt.content.ViewAnswerDiscussion"
|
|
152
|
+
/>
|
|
153
|
+
|
|
154
|
+
<browser:viewlet
|
|
155
|
+
name="plone.comments"
|
|
156
|
+
for="..conclusion.IConclusion"
|
|
157
|
+
layer="plone.app.discussion.interfaces.IDiscussionLayer"
|
|
158
|
+
manager=".interfaces.ICommentDiscussion"
|
|
159
|
+
view="plone.app.layout.globals.interfaces.IViewView"
|
|
160
|
+
class=".comments.CommentsViewlet"
|
|
161
|
+
permission="esdrt.content.ViewConclusionDiscussion"
|
|
162
|
+
/>
|
|
163
|
+
|
|
164
|
+
<browser:viewlet
|
|
165
|
+
name="plone.comments"
|
|
166
|
+
for="..conclusionsphase2.IConclusionsPhase2"
|
|
167
|
+
layer="plone.app.discussion.interfaces.IDiscussionLayer"
|
|
168
|
+
manager=".interfaces.ICommentDiscussion"
|
|
169
|
+
view="plone.app.layout.globals.interfaces.IViewView"
|
|
170
|
+
class=".comments.CommentsViewlet"
|
|
171
|
+
permission="esdrt.content.ViewConclusionDiscussion"
|
|
172
|
+
/>
|
|
173
|
+
|
|
174
|
+
<browser:page
|
|
175
|
+
name="download"
|
|
176
|
+
for="plone.app.discussion.interfaces.IComment"
|
|
177
|
+
class=".attachmentdownload.Download"
|
|
178
|
+
permission="zope2.View"
|
|
179
|
+
/>
|
|
180
|
+
|
|
181
|
+
<browser:page
|
|
182
|
+
name="manage_forcing_workflow_state"
|
|
183
|
+
for="*"
|
|
184
|
+
class=".statechange.UpdateWorkflow"
|
|
185
|
+
permission="cmf.ManagePortal"
|
|
186
|
+
/>
|
|
187
|
+
|
|
188
|
+
<browser:page
|
|
189
|
+
name="observation_import_form"
|
|
190
|
+
for="esdrt.content.reviewfolder.IReviewFolder"
|
|
191
|
+
template="templates/import_observation.pt"
|
|
192
|
+
permission="cmf.ManagePortal"
|
|
193
|
+
/>
|
|
194
|
+
|
|
195
|
+
<browser:page
|
|
196
|
+
name="observation_import"
|
|
197
|
+
for="esdrt.content.reviewfolder.IReviewFolder"
|
|
198
|
+
class=".observation_import.ObservationXLSImport"
|
|
199
|
+
attribute="do_import"
|
|
200
|
+
permission="cmf.ManagePortal"
|
|
201
|
+
/>
|
|
202
|
+
|
|
203
|
+
<browser:page
|
|
204
|
+
name="get_sample_xls"
|
|
205
|
+
for="esdrt.content.reviewfolder.IReviewFolder"
|
|
206
|
+
class=".get_sample_xls.GetSampleXLS"
|
|
207
|
+
permission="cmf.ManagePortal"
|
|
208
|
+
/>
|
|
209
|
+
|
|
210
|
+
<browser:page
|
|
211
|
+
name="macros"
|
|
212
|
+
for="..reviewfolder.IReviewFolder"
|
|
213
|
+
template="templates/macros.pt"
|
|
214
|
+
class=".macros.MacrosView"
|
|
215
|
+
permission="zope2.View"
|
|
216
|
+
/>
|
|
217
|
+
|
|
218
|
+
<browser:page
|
|
219
|
+
name="carryover-form"
|
|
220
|
+
for="esdrt.content.reviewfolder.IReviewFolder"
|
|
221
|
+
class=".carryover.CarryOverView"
|
|
222
|
+
permission="cmf.ManagePortal"
|
|
223
|
+
/>
|
|
224
|
+
|
|
225
|
+
<browser:page
|
|
226
|
+
name="carryover"
|
|
227
|
+
for="esdrt.content.reviewfolder.IReviewFolder"
|
|
228
|
+
class=".carryover.CarryOverView"
|
|
229
|
+
permission="cmf.ManagePortal"
|
|
230
|
+
attribute="start"
|
|
231
|
+
/>
|
|
232
|
+
|
|
233
|
+
</configure>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from Acquisition import aq_inner
|
|
2
|
+
from Acquisition import aq_parent
|
|
3
|
+
from Products.Five import BrowserView
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class CopyFileToAnswer(BrowserView):
|
|
7
|
+
|
|
8
|
+
def render(self):
|
|
9
|
+
context = aq_inner(self.context)
|
|
10
|
+
conversation = aq_parent(context)
|
|
11
|
+
answer = aq_parent(conversation)
|
|
12
|
+
file = getattr(context, 'attachment', None)
|
|
13
|
+
candidate_id = file.filename
|
|
14
|
+
while candidate_id in list(answer.keys()):
|
|
15
|
+
candidate_id += '-1'
|
|
16
|
+
|
|
17
|
+
filename = answer.invokeFactory(
|
|
18
|
+
id=candidate_id,
|
|
19
|
+
type_name='ESDRTFile',
|
|
20
|
+
file=file,
|
|
21
|
+
)
|
|
22
|
+
return self.request.response.redirect(context.absolute_url())
|