270 binfo += u'\n\n:CubicWeb version: %s\n' % (eversion,) |
265 binfo += u'\n\n:CubicWeb version: %s\n' % (eversion,) |
271 for pkg, pkgversion in cubes: |
266 for pkg, pkgversion in cubes: |
272 binfo += u":Package %s version: %s\n" % (pkg, pkgversion) |
267 binfo += u":Package %s version: %s\n" % (pkg, pkgversion) |
273 binfo += '\n' |
268 binfo += '\n' |
274 return binfo |
269 return binfo |
275 |
|
276 # some string we want to be internationalizable for nicer display of eproperty |
|
277 # groups |
|
278 _('navigation') |
|
279 _('ui') |
|
280 _('actions') |
|
281 _('boxes') |
|
282 _('components') |
|
283 _('contentnavigation') |
|
284 |
|
285 |
|
286 def make_togglable_link(nodeid, label, cookiename): |
|
287 """builds a HTML link that switches the visibility & remembers it""" |
|
288 action = u"javascript: toggle_and_remember_visibility('%s', '%s')" % \ |
|
289 (nodeid, cookiename) |
|
290 return u'<a href="%s">%s</a>' % (action, label) |
|
291 |
|
292 def css_class(someclass): |
|
293 return someclass and 'class="%s"' % someclass or '' |
|
294 |
|
295 class SystemEPropertiesForm(FormMixIn, StartupView): |
|
296 id = 'systemepropertiesform' |
|
297 __selectors__ = (none_rset, match_user_groups('managers'),) |
|
298 |
|
299 title = _('site configuration') |
|
300 controller = 'edit' |
|
301 category = 'startupview' |
|
302 |
|
303 def linkable(self): |
|
304 return True |
|
305 |
|
306 def url(self): |
|
307 """return the url associated with this view. We can omit rql here""" |
|
308 return self.build_url('view', vid=self.id) |
|
309 |
|
310 def _cookie_name(self, somestr): |
|
311 return str('%s_property_%s' % (self.config.appid, somestr)) |
|
312 |
|
313 def _group_status(self, group, default=u'hidden'): |
|
314 cookies = self.req.get_cookie() |
|
315 cookiename = self._cookie_name(group) |
|
316 cookie = cookies.get(cookiename) |
|
317 if cookie is None: |
|
318 cookies[cookiename] = default |
|
319 self.req.set_cookie(cookies, cookiename, maxage=None) |
|
320 status = default |
|
321 else: |
|
322 status = cookie.value |
|
323 return status |
|
324 |
|
325 def call(self, **kwargs): |
|
326 """The default view representing the application's index""" |
|
327 self.req.add_js(('cubicweb.edition.js', 'cubicweb.preferences.js')) |
|
328 self.req.add_css('cubicweb.preferences.css') |
|
329 vreg = self.vreg |
|
330 values = self.defined_keys |
|
331 groupedopts = {} |
|
332 mainopts = {} |
|
333 # "self.id=='systemepropertiesform'" to skip site wide properties on |
|
334 # user's preference but not site's configuration |
|
335 for key in vreg.user_property_keys(self.id=='systemepropertiesform'): |
|
336 parts = key.split('.') |
|
337 if parts[0] in vreg: |
|
338 # appobject configuration |
|
339 reg, oid, propid = parts |
|
340 groupedopts.setdefault(reg, {}).setdefault(oid, []).append(key) |
|
341 else: |
|
342 mainopts.setdefault(parts[0], []).append(key) |
|
343 # precompute form to consume error message |
|
344 for group, keys in mainopts.items(): |
|
345 mainopts[group] = self.form(keys, False) |
|
346 for group, objects in groupedopts.items(): |
|
347 for oid, keys in objects.items(): |
|
348 groupedopts[group][oid] = self.form(keys, True) |
|
349 |
|
350 w = self.w |
|
351 req = self.req |
|
352 _ = req._ |
|
353 w(u'<h1>%s</h1>\n' % _(self.title)) |
|
354 w(self.error_message()) |
|
355 for label, group, form in sorted((_(g), g, f) |
|
356 for g, f in mainopts.iteritems()): |
|
357 status = css_class(self._group_status(group)) #'hidden' (collapsed), or '' (open) ? |
|
358 w(u'<h2 class="propertiesform">%s</h2>\n' % |
|
359 (make_togglable_link('fieldset_' + group, label, |
|
360 self._cookie_name(group)))) |
|
361 w(u'<div id="fieldset_%s" %s>' % (group, status)) |
|
362 w(u'<fieldset class="subentity">') |
|
363 w(form) |
|
364 w(u'</fieldset></div>') |
|
365 for label, group, objects in sorted((_(g), g, o) |
|
366 for g, o in groupedopts.iteritems()): |
|
367 status = css_class(self._group_status(group)) |
|
368 w(u'<h2 class="propertiesform">%s</h2>\n' % |
|
369 (make_togglable_link('fieldset_' + group, label, |
|
370 self._cookie_name(group)))) |
|
371 w(u'<div id="fieldset_%s" %s>' % (group, status)) |
|
372 for label, oid, form in sorted((self.req.__('%s_%s' % (group, o)), o, f) |
|
373 for o, f in objects.iteritems()): |
|
374 w(u'<fieldset class="subentity">') |
|
375 w(u'<legend class="componentTitle">%s</legend>\n' % label) |
|
376 docmsgid = '%s_%s_description' % (group, oid) |
|
377 doc = _(docmsgid) |
|
378 if doc != docmsgid: |
|
379 w(u'<p class="description">%s</p>' % html_escape(doc)) |
|
380 w(form) |
|
381 w(u'</fieldset>') |
|
382 w(u'</div>') |
|
383 |
|
384 @property |
|
385 @cached |
|
386 def eprops_rset(self): |
|
387 return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V, NOT P for_user U') |
|
388 |
|
389 @property |
|
390 def defined_keys(self): |
|
391 values = {} |
|
392 for i, entity in enumerate(self.eprops_rset.entities()): |
|
393 values[entity.pkey] = i |
|
394 return values |
|
395 |
|
396 def entity_for_key(self, key): |
|
397 values = self.defined_keys |
|
398 if key in values: |
|
399 entity = self.eprops_rset.get_entity(values[key], 0) |
|
400 else: |
|
401 entity = self.vreg.etype_class('EProperty')(self.req, None, None) |
|
402 entity.eid = self.req.varmaker.next() |
|
403 entity['value'] = self.vreg.property_value(key) |
|
404 return entity |
|
405 |
|
406 def form(self, keys, splitlabel=False): |
|
407 stream = UStringIO() |
|
408 w = stream.write |
|
409 w(u'<form action="%s" method="post">\n' % self.build_url()) |
|
410 w(u'<fieldset>\n') |
|
411 w(u'<input type="hidden" name="__errorurl" value="%s"/>\n' |
|
412 % html_escape(self.req.url())) |
|
413 w(u'<input type="hidden" name="__form_id" value="%s"/>\n' % self.id) |
|
414 path = self.req.relative_path() |
|
415 if '?' in path: |
|
416 path, params = path.split('?', 1) |
|
417 w(u'<input type="hidden" name="__redirectparams" value="%s"/>\n' |
|
418 % html_escape(params)) |
|
419 w(u'<input type="hidden" name="__redirectpath" value="%s"/>\n' % path) |
|
420 #w(u'<input type="hidden" name="__redirectrql" value=""/>\n') |
|
421 w(u'<input type="hidden" name="__message" value="%s"/>\n' |
|
422 % self.req._('changes applied')) |
|
423 w(u'<table><tr><td>\n') |
|
424 |
|
425 w(u'<table>\n') |
|
426 for key in keys: |
|
427 w(u'<tr>\n') |
|
428 self.form_row(w, key, splitlabel) |
|
429 w(u'</tr>\n') |
|
430 w(u'</table>\n') |
|
431 w(u'</td></tr><tr><td>\n') |
|
432 w(self.button_ok()) |
|
433 w(self.button_cancel()) |
|
434 w(u'</td></tr></table>\n') |
|
435 w(u'</fieldset>\n') |
|
436 w(u'</form>\n') |
|
437 return stream.getvalue() |
|
438 |
|
439 def form_row(self, w, key, splitlabel): |
|
440 entity = self.entity_for_key(key) |
|
441 eid = entity.eid |
|
442 if splitlabel: |
|
443 w(u'<td class="label">%s</td>' % self.req._(key.split('.')[-1])) |
|
444 else: |
|
445 w(u'<td class="label">%s</td>' % self.req._(key)) |
|
446 wdg = self.vreg.property_value_widget(key, req=self.req) |
|
447 error = wdg.render_error(entity) |
|
448 w(u'<td class="%s">' % (error and 'error' or '')) |
|
449 w(error) |
|
450 self.form_row_hiddens(w, entity, key) |
|
451 w(wdg.edit_render(entity)) |
|
452 w(u'</td>\n') |
|
453 w(u'<td>%s</td>' % wdg.render_help(entity)) |
|
454 return entity |
|
455 |
|
456 def form_row_hiddens(self, w, entity, key): |
|
457 eid = entity.eid |
|
458 w(u'<input type="hidden" name="eid" value="%s"/>' % eid) |
|
459 w(u'<input type="hidden" name="%s" value="EProperty"/>' % eid_param('__type', eid)) |
|
460 w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('pkey', eid), key)) |
|
461 w(u'<input type="hidden" name="%s" value="%s"/>' % (eid_param('edits-pkey', eid), '')) |
|
462 |
|
463 |
|
464 |
|
465 def is_user_prefs(cls, req, rset, row, col): |
|
466 return req.user.eid == rset[row or 0 ][col or 0] |
|
467 |
|
468 class EPropertiesForm(SystemEPropertiesForm): |
|
469 id = 'epropertiesform' |
|
470 __selectors__ = ( |
|
471 # we don't want guests to be able to come here |
|
472 match_user_groups('users', 'managers'), |
|
473 chainfirst(none_rset), |
|
474 chainall(one_line_rset, is_user_prefs), |
|
475 chainall(one_line_rset, match_user_groups('managers')) |
|
476 ) |
|
477 |
|
478 __selectors__ = (implements('EUser',)) |
|
479 |
|
480 title = _('preferences') |
|
481 |
|
482 @property |
|
483 def user(self): |
|
484 if self.rset is None: |
|
485 return self.req.user |
|
486 return self.rset.get_entity(self.row or 0, self.col or 0) |
|
487 |
|
488 @property |
|
489 @cached |
|
490 def eprops_rset(self): |
|
491 return self.req.execute('Any P,K,V WHERE P is EProperty, P pkey K, P value V,' |
|
492 'P for_user U, U eid %(x)s', {'x': self.user.eid}) |
|
493 |
|
494 def form_row_hiddens(self, w, entity, key): |
|
495 super(EPropertiesForm, self).form_row_hiddens(w, entity, key) |
|
496 # if user is in the managers group and the property is being created, |
|
497 # we have to set for_user explicitly |
|
498 if not entity.has_eid() and self.user.matching_groups('managers'): |
|
499 eid = entity.eid |
|
500 w(u'<input type="hidden" name="%s" value="%s"/>' |
|
501 % (eid_param('edits-for_user', eid), INTERNAL_FIELD_VALUE)) |
|
502 w(u'<input type="hidden" name="%s" value="%s"/>' |
|
503 % (eid_param('for_user', eid), self.user.eid)) |
|
504 |
|
505 |
|
506 |
|
507 |
270 |
508 class ProcessInformationView(StartupView): |
271 class ProcessInformationView(StartupView): |
509 id = 'info' |
272 id = 'info' |
510 __selectors__ = (none_rset, match_user_groups('managers'),) |
273 __selectors__ = (none_rset, match_user_groups('managers'),) |
511 |
274 |