|
1 """Set of HTML base actions |
|
2 |
|
3 :organization: Logilab |
|
4 :copyright: 2001-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
5 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
6 """ |
|
7 __docformat__ = "restructuredtext en" |
|
8 |
|
9 from cubicweb import UnknownEid |
|
10 from cubicweb.common.selectors import * |
|
11 |
|
12 from cubicweb.web.action import (Action, EntityAction, LinkToEntityAction, |
|
13 LinkToEntityAction2) |
|
14 from cubicweb.web.views import linksearch_select_url, linksearch_match |
|
15 from cubicweb.web.views.baseviews import vid_from_rset |
|
16 |
|
17 _ = unicode |
|
18 |
|
19 |
|
20 class SelectAction(EntityAction): |
|
21 """base class for link search actions. By default apply on |
|
22 any size entity result search it the current state is 'linksearch' |
|
23 if accept match. |
|
24 """ |
|
25 category = 'mainactions' |
|
26 __selectors__ = (searchstate_accept_selector,) |
|
27 search_states = ('linksearch',) |
|
28 order = 0 |
|
29 |
|
30 id = 'select' |
|
31 title = _('select') |
|
32 |
|
33 @classmethod |
|
34 def accept_rset(cls, req, rset, row, col): |
|
35 return linksearch_match(req, rset) |
|
36 |
|
37 def url(self): |
|
38 return linksearch_select_url(self.req, self.rset) |
|
39 |
|
40 |
|
41 class CancelSelectAction(Action): |
|
42 category = 'mainactions' |
|
43 search_states = ('linksearch',) |
|
44 order = 10 |
|
45 |
|
46 id = 'cancel' |
|
47 title = _('cancel select') |
|
48 |
|
49 def url(self): |
|
50 target, link_eid, r_type, searched_type = self.req.search_state[1] |
|
51 return self.build_url(rql="Any X WHERE X eid %s" % link_eid, |
|
52 vid='edition', __mode='normal') |
|
53 |
|
54 |
|
55 class ViewAction(Action): |
|
56 category = 'mainactions' |
|
57 __selectors__ = (in_group_selector, searchstate_accept_selector) |
|
58 require_groups = ('users', 'managers') |
|
59 order = 0 |
|
60 |
|
61 id = 'view' |
|
62 title = _('view') |
|
63 |
|
64 @classmethod |
|
65 def accept_rset(cls, req, rset, row, col): |
|
66 # interesting if it propose another view than the current one |
|
67 vid = req.form.get('vid') |
|
68 if vid and vid != vid_from_rset(req, rset, cls.schema): |
|
69 return 1 |
|
70 return 0 |
|
71 |
|
72 def url(self): |
|
73 params = self.req.form.copy() |
|
74 params.pop('vid', None) |
|
75 params.pop('__message', None) |
|
76 return self.build_url(self.req.relative_path(includeparams=False), **params) |
|
77 |
|
78 |
|
79 class ModifyAction(EntityAction): |
|
80 category = 'mainactions' |
|
81 __selectors__ = (onelinerset_selector, searchstate_accept_selector) |
|
82 #__selectors__ = searchstate_accept_selector, |
|
83 schema_action = 'update' |
|
84 order = 10 |
|
85 |
|
86 id = 'edit' |
|
87 title = _('modify') |
|
88 |
|
89 @classmethod |
|
90 def has_permission(cls, entity, action): |
|
91 if entity.has_perm(action): |
|
92 return True |
|
93 # if user has no update right but it can modify some relation, |
|
94 # display action anyway |
|
95 for dummy in entity.srelations_by_category(('generic', 'metadata'), 'add'): |
|
96 return True |
|
97 for rschema, targetschemas, role in entity.relations_by_category(('primary', 'secondary'), 'add'): |
|
98 if not rschema.is_final(): |
|
99 return True |
|
100 return False |
|
101 |
|
102 def url(self): |
|
103 entity = self.rset.get_entity(self.row or 0, self.col or 0) |
|
104 return entity.absolute_url(vid='edition') |
|
105 |
|
106 |
|
107 class DeleteAction(EntityAction): |
|
108 category = 'moreactions' |
|
109 __selectors__ = (searchstate_accept_selector,) |
|
110 schema_action = 'delete' |
|
111 order = 20 |
|
112 |
|
113 id = 'delete' |
|
114 title = _('delete') |
|
115 |
|
116 def url(self): |
|
117 if len(self.rset) == 1: |
|
118 entity = self.rset.get_entity(0, 0) |
|
119 return self.build_url(entity.rest_path(), vid='deleteconf') |
|
120 return self.build_url(rql=self.rset.printable_rql(), vid='deleteconf') |
|
121 |
|
122 |
|
123 class CopyAction(EntityAction): |
|
124 category = 'moreactions' |
|
125 schema_action = 'add' |
|
126 order = 30 |
|
127 |
|
128 id = 'copy' |
|
129 title = _('copy') |
|
130 |
|
131 def url(self): |
|
132 entity = self.rset.get_entity(self.row or 0, self.col or 0) |
|
133 return entity.absolute_url(vid='copy') |
|
134 |
|
135 |
|
136 class MultipleEditAction(EntityAction): |
|
137 category = 'mainactions' |
|
138 __selectors__ = (twolinerset_selector, oneetyperset_selector, |
|
139 searchstate_accept_selector) |
|
140 schema_action = 'update' |
|
141 order = 10 |
|
142 |
|
143 id = 'muledit' # XXX get strange conflicts if id='edit' |
|
144 title = _('modify') |
|
145 |
|
146 def url(self): |
|
147 return self.build_url('view', rql=self.rset.rql, vid='muledit') |
|
148 |
|
149 |
|
150 class AddNewAction(MultipleEditAction): |
|
151 """when we're seeing more than one entity with the same type, propose to |
|
152 add a new one |
|
153 """ |
|
154 category = 'moreactions' |
|
155 |
|
156 def etype_rset_selector(cls, req, rset, **kwargs): |
|
157 if rset is not None and not rset.rowcount: |
|
158 rqlst = rset.syntax_tree() |
|
159 if len(rqlst.children) > 1: |
|
160 return 0 |
|
161 select = rqlst.children[0] |
|
162 if len(select.defined_vars) == 1 and len(select.solutions) == 1: |
|
163 rset._searched_etype = select.solutions[0].itervalues().next() |
|
164 eschema = cls.schema.eschema(rset._searched_etype) |
|
165 if not eschema.is_final() and eschema.has_perm(req, 'add'): |
|
166 return 1 |
|
167 return 0 |
|
168 |
|
169 def has_add_perm_selector(cls, req, rset, **kwargs): |
|
170 eschema = cls.schema.eschema(rset.description[0][0]) |
|
171 if not eschema.is_final() and eschema.has_perm(req, 'add'): |
|
172 return 1 |
|
173 return 0 |
|
174 __selectors__ = (searchstate_selector, |
|
175 chainfirst(etype_rset_selector, |
|
176 chainall(twolinerset_selector, oneetyperset_selector, |
|
177 has_add_perm_selector))) |
|
178 order = 40 |
|
179 id = 'addentity' |
|
180 |
|
181 @property |
|
182 def rsettype(self): |
|
183 if self.rset: |
|
184 return self.rset.description[0][0] |
|
185 return self.rset._searched_etype |
|
186 |
|
187 @property |
|
188 def title(self): |
|
189 return self.req.__('add a %s' % self.rsettype) # generated msgid |
|
190 |
|
191 def url(self): |
|
192 return self.build_url('add/%s' % self.rsettype) |
|
193 |
|
194 |
|
195 class FollowAction(EntityAction): |
|
196 category = 'mainactions' |
|
197 accepts = ('Bookmark',) |
|
198 |
|
199 id = 'follow' |
|
200 title = _('follow') |
|
201 |
|
202 def url(self): |
|
203 return self.rset.get_entity(self.row or 0, self.col or 0).actual_url() |
|
204 |
|
205 class UserPreferencesAction(Action): |
|
206 category = 'useractions' |
|
207 __selectors__ = not_anonymous_selector, |
|
208 order = 10 |
|
209 |
|
210 id = 'myprefs' |
|
211 title = _('user preferences') |
|
212 |
|
213 def url(self): |
|
214 return self.build_url(self.id) |
|
215 |
|
216 class UserPreferencesEntityAction(EntityAction): |
|
217 __selectors__ = EntityAction.__selectors__ + (onelinerset_selector, in_group_selector,) |
|
218 require_groups = ('owners', 'managers') |
|
219 category = 'mainactions' |
|
220 accepts = ('EUser',) |
|
221 |
|
222 id = 'prefs' |
|
223 title = _('preferences') |
|
224 |
|
225 def url(self): |
|
226 login = self.rset.get_entity(self.row or 0, self.col or 0).login |
|
227 return self.build_url('euser/%s'%login, vid='epropertiesform') |
|
228 |
|
229 class UserInfoAction(Action): |
|
230 category = 'useractions' |
|
231 __selectors__ = not_anonymous_selector, |
|
232 order = 20 |
|
233 |
|
234 id = 'myinfos' |
|
235 title = _('personnal informations') |
|
236 |
|
237 def url(self): |
|
238 return self.build_url('euser/%s'%self.req.user.login, vid='edition') |
|
239 |
|
240 class LogoutAction(Action): |
|
241 category = 'useractions' |
|
242 __selectors__ = not_anonymous_selector, |
|
243 order = 30 |
|
244 |
|
245 id = 'logout' |
|
246 title = _('logout') |
|
247 |
|
248 def url(self): |
|
249 return self.build_url(self.id) |
|
250 |
|
251 |
|
252 class ManagersAction(Action): |
|
253 category = 'siteactions' |
|
254 __abstract__ = True |
|
255 __selectors__ = in_group_selector, |
|
256 require_groups = ('managers',) |
|
257 |
|
258 def url(self): |
|
259 return self.build_url(self.id) |
|
260 |
|
261 class SiteConfigurationAction(ManagersAction): |
|
262 order = 10 |
|
263 |
|
264 id = 'siteconfig' |
|
265 title = _('site configuration') |
|
266 |
|
267 class ManageAction(ManagersAction): |
|
268 order = 20 |
|
269 |
|
270 id = 'manage' |
|
271 title = _('manage') |
|
272 |
|
273 |
|
274 class ViewSchemaAction(Action): |
|
275 category = 'siteactions' |
|
276 __selectors__ = yes_selector, |
|
277 order = 30 |
|
278 |
|
279 id = 'schema' |
|
280 title = _("site schema") |
|
281 |
|
282 def url(self): |
|
283 return self.build_url(self.id) |
|
284 |