1
|
|
|
# -*- coding: utf-8 -*- |
2
|
|
|
|
3
|
|
|
from AccessControl import ClassSecurityInfo |
4
|
|
|
from bika.lims import senaiteMessageFactory as _ |
5
|
|
|
from plone.autoform import directives |
6
|
|
|
from plone.autoform.interfaces import IFormFieldProvider |
7
|
|
|
from plone.behavior.interfaces import IBehaviorAssignable |
8
|
|
|
from plone.behavior.registration import BehaviorRegistration |
9
|
|
|
from plone.dexterity.behavior import DexterityBehaviorAssignable |
10
|
|
|
from plone.dexterity.schema import SCHEMA_CACHE |
11
|
|
|
from plone.supermodel import model |
12
|
|
|
from plone.supermodel.directives import fieldset |
13
|
|
|
from Products.CMFCore import permissions |
14
|
|
|
from senaite.core.api import label as label_api |
15
|
|
|
from senaite.core.catalog import SETUP_CATALOG |
16
|
|
|
from senaite.core.interfaces import ICanHaveLabels |
17
|
|
|
from senaite.core.z3cform.widgets.queryselect import QuerySelectWidgetFactory |
18
|
|
|
from zope import schema |
19
|
|
|
from zope.component import adapter |
20
|
|
|
from zope.interface import implementer |
21
|
|
|
from zope.interface import provider |
22
|
|
|
|
23
|
|
|
|
24
|
|
|
@implementer(IBehaviorAssignable) |
25
|
|
|
@adapter(ICanHaveLabels) |
26
|
|
|
class LabelBehaviorAssignable(DexterityBehaviorAssignable): |
27
|
|
|
"""Extend label behavior if the context provides the interface `ICanHaveLabels` |
28
|
|
|
""" |
29
|
|
|
def __init__(self, context): |
30
|
|
|
self.context = context |
31
|
|
|
|
32
|
|
|
def supports(self, behavior_interface): |
33
|
|
|
for behavior in self.enumerateBehaviors(): |
34
|
|
|
if behavior_interface in behavior.interface._implied: |
35
|
|
|
return True |
36
|
|
|
return False |
37
|
|
|
|
38
|
|
|
def enumerateBehaviors(self): |
39
|
|
|
portal_type = self.context.portal_type |
40
|
|
|
behaviors = SCHEMA_CACHE.behavior_registrations(portal_type) |
41
|
|
|
registered = False |
42
|
|
|
for behavior in behaviors: |
43
|
|
|
if behavior.marker == ICanHaveLabels: |
44
|
|
|
registered = True |
45
|
|
|
yield behavior |
46
|
|
|
# additionally yield the schema registration if it was not already |
47
|
|
|
# registered via the FTI |
48
|
|
|
if not registered: |
49
|
|
|
yield self.label_registration |
50
|
|
|
|
51
|
|
|
@property |
52
|
|
|
def label_registration(self): |
53
|
|
|
return BehaviorRegistration( |
54
|
|
|
title="Label schema extender", |
55
|
|
|
description="Adds the ability to add/remove labels", |
56
|
|
|
interface=ILabelSchema, |
57
|
|
|
marker=ICanHaveLabels, |
58
|
|
|
factory=LabelSchema, |
59
|
|
|
) |
60
|
|
|
|
61
|
|
|
|
62
|
|
|
@provider(IFormFieldProvider) |
63
|
|
|
class ILabelSchema(model.Schema): |
64
|
|
|
"""Behavior with schema fields to allow to add/remove labels |
65
|
|
|
""" |
66
|
|
|
fieldset( |
67
|
|
|
"labels", |
68
|
|
|
label=u"Labels", |
69
|
|
|
fields=["Labels"]) |
70
|
|
|
|
71
|
|
|
directives.widget( |
72
|
|
|
"Labels", |
73
|
|
|
QuerySelectWidgetFactory, |
74
|
|
|
catalog=SETUP_CATALOG, |
75
|
|
|
search_index="Title", |
76
|
|
|
value_key="title", |
77
|
|
|
search_wildcard=True, |
78
|
|
|
multi_valued=True, |
79
|
|
|
allow_user_value=True, |
80
|
|
|
hide_input_after_select=False, |
81
|
|
|
query={ |
82
|
|
|
"portal_type": "Label", |
83
|
|
|
"is_active": True, |
84
|
|
|
"sort_on": "title", |
85
|
|
|
}, |
86
|
|
|
columns=[ |
87
|
|
|
{ |
88
|
|
|
"name": "title", |
89
|
|
|
"width": "100", |
90
|
|
|
"align": "left", |
91
|
|
|
"label": _(u"Label"), |
92
|
|
|
}, |
93
|
|
|
], |
94
|
|
|
display_template="<a href='${url}'>${title}</a>", |
95
|
|
|
limit=5, |
96
|
|
|
) |
97
|
|
|
Labels = schema.List( |
98
|
|
|
title=_(u"label_Labels", default=u"Labels"), |
99
|
|
|
description=_(u"description_Labels", default=u"Attached labels"), |
100
|
|
|
value_type=schema.TextLine(title=u"Label"), |
101
|
|
|
required=False, |
102
|
|
|
) |
103
|
|
|
|
104
|
|
|
|
105
|
|
|
@implementer(ILabelSchema) |
106
|
|
|
@adapter(ICanHaveLabels) |
107
|
|
|
class LabelSchema(object): |
108
|
|
|
"""Factory that provides the extended label fields |
109
|
|
|
""" |
110
|
|
|
security = ClassSecurityInfo() |
111
|
|
|
|
112
|
|
|
def __init__(self, context): |
113
|
|
|
self.context = context |
114
|
|
|
|
115
|
|
|
@security.protected(permissions.View) |
116
|
|
|
def getLabels(self): |
117
|
|
|
return label_api.get_obj_labels(self.context) |
118
|
|
|
|
119
|
|
|
@security.protected(permissions.ModifyPortalContent) |
120
|
|
|
def setLabels(self, value): |
121
|
|
|
labels = label_api.to_labels(value) |
122
|
|
|
return label_api.set_obj_labels(self.context, labels) |
123
|
|
|
|
124
|
|
|
Labels = property(getLabels, setLabels) |
125
|
|
|
|