actions.py 7.49 KB
Newer Older
Adrien Di Mascio's avatar
Adrien Di Mascio committed
1
2
3
"""Set of HTML base actions

:organization: Logilab
4
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
Adrien Di Mascio's avatar
Adrien Di Mascio committed
5
6
7
8
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
"""
__docformat__ = "restructuredtext en"

9
from cubicweb.selectors import (
10
11
12
13
14
15
16
17
    yes, one_line_rset, two_lines_rset, one_etype_rset, relation_possible,
    non_final_entity,
    authenticated_user, match_user_groups, match_search_state,
    has_editable_relation, has_permission, has_add_permission,
    )

from cubicweb.web.action import Action
from cubicweb.web.views import linksearch_select_url
Adrien Di Mascio's avatar
Adrien Di Mascio committed
18
19
20
21
from cubicweb.web.views.baseviews import vid_from_rset

_ = unicode

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
def match_searched_etype(cls, req, rset, row=None, col=None, **kwargs):
    return req.match_search_state(rset)

def view_is_not_default_view(cls, req, rset, row, col, **kwargs):
    # interesting if it propose another view than the current one
    vid = req.form.get('vid')
    if vid and vid != vid_from_rset(req, rset, cls.schema):
        return 1
    return 0

def addable_etype_empty_rset(cls, req, rset, **kwargs):
    if rset is not None and not rset.rowcount:
        rqlst = rset.syntax_tree()
        if len(rqlst.children) > 1:
            return 0
        select = rqlst.children[0]
        if len(select.defined_vars) == 1 and len(select.solutions) == 1:
            rset._searched_etype = select.solutions[0].itervalues().next()
            eschema = cls.schema.eschema(rset._searched_etype)
            if not (eschema.is_final() or eschema.is_subobject(strict=True)) \
                   and eschema.has_perm(req, 'add'):
                return 1
    return 0

46
# generic primary actions #####################################################
Adrien Di Mascio's avatar
Adrien Di Mascio committed
47

48
class SelectAction(Action):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
49
50
51
52
53
    """base class for link search actions. By default apply on
    any size entity result search it the current state is 'linksearch'
    if accept match.
    """
    id = 'select'
54
    __select__ = match_search_state('linksearch') & match_searched_etype()
Adrien Di Mascio's avatar
Adrien Di Mascio committed
55
    
56
57
58
    title = _('select')
    category = 'mainactions'    
    order = 0
Adrien Di Mascio's avatar
Adrien Di Mascio committed
59
60
61
62
63
64
65
    
    def url(self):
        return linksearch_select_url(self.req, self.rset)


class CancelSelectAction(Action):
    id = 'cancel'
66
    __select__ = match_search_state('linksearch')
67
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
68
    title = _('cancel select')
69
70
    category = 'mainactions'
    order = 10
Adrien Di Mascio's avatar
Adrien Di Mascio committed
71
72
    
    def url(self):
73
74
        target, eid, r_type, searched_type = self.req.search_state[1]
        return self.build_url(str(eid),
Adrien Di Mascio's avatar
Adrien Di Mascio committed
75
76
77
78
79
                              vid='edition', __mode='normal')


class ViewAction(Action):
    id = 'view'
80
81
82
83
    __select__ = (match_search_state('normal') &
                  match_user_groups('users', 'managers') &
                  view_is_not_default_view() & 
                  non_final_entity())
Adrien Di Mascio's avatar
Adrien Di Mascio committed
84
    
85
86
87
    title = _('view')
    category = 'mainactions'    
    order = 0
Adrien Di Mascio's avatar
Adrien Di Mascio committed
88
89
90
91
92
    
    def url(self):
        params = self.req.form.copy()
        params.pop('vid', None)
        params.pop('__message', None)
93
94
        return self.build_url(self.req.relative_path(includeparams=False),
                              **params)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
95
96


97
class ModifyAction(Action):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
98
    id = 'edit'
99
100
101
    __select__ = (match_search_state('normal') &
                  one_line_rset() & 
                  (has_permission('update') | has_editable_relation('add')))
Adrien Di Mascio's avatar
Adrien Di Mascio committed
102
    
103
104
105
    title = _('modify')
    category = 'mainactions'
    order = 10
Adrien Di Mascio's avatar
Adrien Di Mascio committed
106
107
108
109

    def url(self):
        entity = self.rset.get_entity(self.row or 0, self.col or 0)
        return entity.absolute_url(vid='edition')
110
111
        

112
class MultipleEditAction(Action):
113
    id = 'muledit' # XXX get strange conflicts if id='edit'
114
115
116
    __select__ = (match_search_state('normal') &
                     two_lines_rset(), one_etype_rset() &
                  has_permission('update'))
117

118
    title = _('modify')
119
120
    category = 'mainactions'
    order = 10
121
122
123
124
125
126
127
    
    def url(self):
        return self.build_url('view', rql=self.rset.rql, vid='muledit')


# generic secondary actions ###################################################

128
class ManagePermissionsAction(Action):
129
    id = 'addpermission'
130
    __select__ = match_user_groups('managers') 
131

132
    title = _('manage permissions')
133
    category = 'moreactions'
134
    order = 100
135

136
    @classmethod
137
138
    def registered(cls, vreg):
        if 'require_permission' in vreg.schema:
139
140
141
142
            cls.__select__ |= relation_possible('require_permission', 'subject', 'EPermission',
                                                action='add')
        return super(ManagePermissionsAction, cls).registered(vreg)
    
143
144
    def url(self):
        return self.rset.get_entity(0, 0).absolute_url(vid='security')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
145
146

    
147
class DeleteAction(Action):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
148
    id = 'delete'
149
    __select__ = one_line_rset() & has_permission('delete')
150
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
151
    title = _('delete')
152
153
    category = 'moreactions' 
    order = 20
Adrien Di Mascio's avatar
Adrien Di Mascio committed
154
155
156
157
158
159
160
161
    
    def url(self):
        if len(self.rset) == 1:
            entity = self.rset.get_entity(0, 0)
            return self.build_url(entity.rest_path(), vid='deleteconf')
        return self.build_url(rql=self.rset.printable_rql(), vid='deleteconf')
    
        
162
class CopyAction(Action):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
163
    id = 'copy'
164
    __select__ = one_line_rset() & has_permission('add')
165
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
166
    title = _('copy')
167
168
    category = 'moreactions'
    order = 30
Adrien Di Mascio's avatar
Adrien Di Mascio committed
169
170
171
172
173
174
175
176
177
178
    
    def url(self):
        entity = self.rset.get_entity(self.row or 0, self.col or 0)
        return entity.absolute_url(vid='copy')


class AddNewAction(MultipleEditAction):
    """when we're seeing more than one entity with the same type, propose to
    add a new one
    """
179
    id = 'addentity'
180
181
182
183
    __select__ = (match_search_state('normal') &
                  (addable_etype_empty_rset()
                   | (two_lines_rset() & one_etype_rset &  & has_add_permission()))
                  )
184
185

    category = 'moreactions'
186
    order = 40
Adrien Di Mascio's avatar
Adrien Di Mascio committed
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
    
    @property
    def rsettype(self):
        if self.rset:
            return self.rset.description[0][0]
        return self.rset._searched_etype

    @property
    def title(self):
        return self.req.__('add a %s' % self.rsettype) # generated msgid

    def url(self):
        return self.build_url('add/%s' % self.rsettype)


202
# logged user actions #########################################################
Adrien Di Mascio's avatar
Adrien Di Mascio committed
203
204
205

class UserPreferencesAction(Action):
    id = 'myprefs'
206
    __select__ = authenticated_user()
207
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
208
    title = _('user preferences')
209
210
    category = 'useractions'
    order = 10
Adrien Di Mascio's avatar
Adrien Di Mascio committed
211
212
213
214
215
216
217

    def url(self):
        return self.build_url(self.id)


class UserInfoAction(Action):
    id = 'myinfos'
218
    __select__ = authenticated_user()
219
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
220
    title = _('personnal informations')
221
222
    category = 'useractions'
    order = 20
Adrien Di Mascio's avatar
Adrien Di Mascio committed
223
224
225
226

    def url(self):
        return self.build_url('euser/%s'%self.req.user.login, vid='edition')

227

Adrien Di Mascio's avatar
Adrien Di Mascio committed
228
229
class LogoutAction(Action):
    id = 'logout'
230
    __select__ = authenticated_user()
231
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
232
    title = _('logout')
233
234
    category = 'useractions'
    order = 30
Adrien Di Mascio's avatar
Adrien Di Mascio committed
235
236
237

    def url(self):
        return self.build_url(self.id)
238

Adrien Di Mascio's avatar
Adrien Di Mascio committed
239
    
240
# site actions ################################################################
Adrien Di Mascio's avatar
Adrien Di Mascio committed
241
242
243

class ManagersAction(Action):
    __abstract__ = True
244
    __select__ = match_user_groups('managers')
245
246

    category = 'siteactions'
Adrien Di Mascio's avatar
Adrien Di Mascio committed
247
248
249

    def url(self):
        return self.build_url(self.id)
250

Adrien Di Mascio's avatar
Adrien Di Mascio committed
251
252
253
254
    
class SiteConfigurationAction(ManagersAction):
    id = 'siteconfig'
    title = _('site configuration')
255
    order = 10
256

Adrien Di Mascio's avatar
Adrien Di Mascio committed
257
258
259
260
    
class ManageAction(ManagersAction):
    id = 'manage'
    title = _('manage')
261
    order = 20
Adrien Di Mascio's avatar
Adrien Di Mascio committed
262
263
264


class ViewSchemaAction(Action):
265
    id = 'schema'
266
    __select__ = yes()
267
    
268
    title = _("site schema")
269
    category = 'siteactions'
Adrien Di Mascio's avatar
Adrien Di Mascio committed
270
271
272
273
    order = 30
    
    def url(self):
        return self.build_url(self.id)