actions.py 7.41 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
10
11
12
13
14
15
16
17
from cubicweb.common.selectors import (
    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
55
    __selectors__ = (match_search_state('linksearch'),
                     match_searched_etype)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
56
    
57
58
59
    title = _('select')
    category = 'mainactions'    
    order = 0
Adrien Di Mascio's avatar
Adrien Di Mascio committed
60
61
62
63
64
65
66
    
    def url(self):
        return linksearch_select_url(self.req, self.rset)


class CancelSelectAction(Action):
    id = 'cancel'
67
68
    __selectors__ = (match_search_state('linksearch'),)
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
69
    title = _('cancel select')
70
71
    category = 'mainactions'
    order = 10
Adrien Di Mascio's avatar
Adrien Di Mascio committed
72
73
    
    def url(self):
74
75
        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
76
77
78
79
80
                              vid='edition', __mode='normal')


class ViewAction(Action):
    id = 'view'
81
82
83
84
    __selectors__ = (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
85
    
86
87
88
    title = _('view')
    category = 'mainactions'    
    order = 0
Adrien Di Mascio's avatar
Adrien Di Mascio committed
89
90
91
92
93
    
    def url(self):
        params = self.req.form.copy()
        params.pop('vid', None)
        params.pop('__message', None)
94
95
        return self.build_url(self.req.relative_path(includeparams=False),
                              **params)
Adrien Di Mascio's avatar
Adrien Di Mascio committed
96
97


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

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

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

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


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

129
class ManagePermissions(Action):
130
    id = 'addpermission'
131
132
133
134
135
    __selectors__ = (
        (match_user_groups('managers') 
         | relation_possible('require_permission', 'subject', 'EPermission')),
                   )

136
    title = _('manage permissions')
137
    category = 'moreactions'
138
139
140
141
    order = 100
    
    def url(self):
        return self.rset.get_entity(0, 0).absolute_url(vid='security')
Adrien Di Mascio's avatar
Adrien Di Mascio committed
142
143

    
144
class DeleteAction(Action):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
145
    id = 'delete'
146
147
    __selectors__ = (has_permission('delete'),)
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
148
    title = _('delete')
149
150
    category = 'moreactions' 
    order = 20
Adrien Di Mascio's avatar
Adrien Di Mascio committed
151
152
153
154
155
156
157
158
    
    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')
    
        
159
class CopyAction(Action):
Adrien Di Mascio's avatar
Adrien Di Mascio committed
160
    id = 'copy'
161
162
    __selectors__ = (has_permission('add'),)
    
Adrien Di Mascio's avatar
Adrien Di Mascio committed
163
    title = _('copy')
164
165
    category = 'moreactions'
    order = 30
Adrien Di Mascio's avatar
Adrien Di Mascio committed
166
167
168
169
170
171
172
173
174
175
    
    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
    """
176
    id = 'addentity'
177
178
179
180
181
182
183
    __selectors__ = (match_search_state('normal'),
                     (addable_etype_empty_rset
                      # XXX has_add_permission in the middle so '&' is available
                      | (two_lines_rset & has_add_permission() & one_etype_rset ))
                     )

    category = 'moreactions'
184
    order = 40
Adrien Di Mascio's avatar
Adrien Di Mascio committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    
    @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)


200
# logged user actions #########################################################
Adrien Di Mascio's avatar
Adrien Di Mascio committed
201
202
203

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

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


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

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

225

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

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

Adrien Di Mascio's avatar
Adrien Di Mascio committed
237
    
238
# site actions ################################################################
Adrien Di Mascio's avatar
Adrien Di Mascio committed
239
240
241

class ManagersAction(Action):
    __abstract__ = True
242
243
244
    __selectors__ = (match_user_groups('managers'),)

    category = 'siteactions'
Adrien Di Mascio's avatar
Adrien Di Mascio committed
245
246
247

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

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

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


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