diff -r a721966779be -r cba9f175da2d web/views/eproperties.py --- a/web/views/eproperties.py Thu May 07 16:33:22 2009 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,329 +0,0 @@ -"""Specific views for CWProperty - -:organization: Logilab -:copyright: 2007-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. -:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr -""" -__docformat__ = "restructuredtext en" - -from logilab.mtconverter import html_escape - -from logilab.common.decorators import cached - -from cubicweb import UnknownProperty -from cubicweb.selectors import (one_line_rset, none_rset, implements, - match_user_groups, entity_implements) -from cubicweb.utils import UStringIO -from cubicweb.view import StartupView -from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, uicfg -from cubicweb.web.views import baseviews -from cubicweb.web import stdmsgs -from cubicweb.web.form import CompositeForm, EntityFieldsForm, FormViewMixIn -from cubicweb.web.formfields import FIELDS, StringField -from cubicweb.web.formwidgets import Select, Button, SubmitButton - -_ = unicode - -# some string we want to be internationalizable for nicer display of eproperty -# groups -_('navigation') -_('ui') -_('actions') -_('boxes') -_('components') -_('contentnavigation') - - -def make_togglable_link(nodeid, label, cookiename): - """builds a HTML link that switches the visibility & remembers it""" - action = u"javascript: toggle_and_remember_visibility('%s', '%s')" % \ - (nodeid, cookiename) - return u'%s' % (action, label) - -def css_class(someclass): - return someclass and 'class="%s"' % someclass or '' - - -class CWPropertyPrimaryView(baseviews.PrimaryView): - __select__ = implements('CWProperty') - skip_none = False - - -class SystemEPropertiesForm(FormViewMixIn, StartupView): - id = 'systemepropertiesform' - __select__ = none_rset() & match_user_groups('managers') - - title = _('site configuration') - category = 'startupview' - - def linkable(self): - return True - - def url(self): - """return the url associated with this view. We can omit rql here""" - return self.build_url('view', vid=self.id) - - def _cookie_name(self, somestr): - return str('%s_property_%s' % (self.config.appid, somestr)) - - def _group_status(self, group, default=u'hidden'): - """return css class name 'hidden' (collapsed), or '' (open)""" - cookies = self.req.get_cookie() - cookiename = self._cookie_name(group) - cookie = cookies.get(cookiename) - if cookie is None: - cookies[cookiename] = default - self.req.set_cookie(cookies, cookiename, maxage=None) - status = default - else: - status = cookie.value - return status - - def call(self, **kwargs): - """The default view representing the application's index""" - self.req.add_js('cubicweb.preferences.js') - self.req.add_css('cubicweb.preferences.css') - vreg = self.vreg - values = self.defined_keys - groupedopts = {} - mainopts = {} - # "self.id=='systemepropertiesform'" to skip site wide properties on - # user's preference but not site's configuration - for key in vreg.user_property_keys(self.id=='systemepropertiesform'): - parts = key.split('.') - if parts[0] in vreg: - # appobject configuration - reg, oid, propid = parts - groupedopts.setdefault(reg, {}).setdefault(oid, []).append(key) - else: - mainopts.setdefault(parts[0], []).append(key) - # precompute form to consume error message - for group, keys in mainopts.items(): - mainopts[group] = self.form(keys, True) - for group, objects in groupedopts.items(): - for oid, keys in objects.items(): - groupedopts[group][oid] = self.form(keys, True) - w = self.w - req = self.req - _ = req._ - w(u'

%s

\n' % _(self.title)) - # we don't want this in each sub-forms - w(u'
%s
' % self.req._('validating...')) - for label, group, form in sorted((_(g), g, f) - for g, f in mainopts.iteritems()): - status = css_class(self._group_status(group)) - w(u'

%s

\n' % - (make_togglable_link('fieldset_' + group, label, - self._cookie_name(group)))) - w(u'
' % (group, status)) - w(form) - w(u'
') - for label, group, objects in sorted((_(g), g, o) - for g, o in groupedopts.iteritems()): - status = css_class(self._group_status(group)) - w(u'

%s

\n' % - (make_togglable_link('fieldset_' + group, label, - self._cookie_name(group)))) - w(u'
' % (group, status)) - for label, oid, form in sorted((self.req.__('%s_%s' % (group, o)), o, f) - for o, f in objects.iteritems()): - w(u'
') - w(u'%s\n' % label) - docmsgid = '%s_%s_description' % (group, oid) - doc = _(docmsgid) - if doc != docmsgid: - w(u'

%s

' % html_escape(doc)) - w(form) - w(u'
') - w(u'
') - - @property - @cached - def eprops_rset(self): - return self.req.execute('Any P,K,V WHERE P is CWProperty, P pkey K, ' - 'P value V, NOT P for_user U') - - @property - def defined_keys(self): - values = {} - for i, entity in enumerate(self.eprops_rset.entities()): - values[entity.pkey] = i - return values - - def entity_for_key(self, key): - values = self.defined_keys - if key in values: - entity = self.eprops_rset.get_entity(values[key], 0) - else: - entity = self.vreg.etype_class('CWProperty')(self.req, None, None) - entity.eid = self.req.varmaker.next() - entity['pkey'] = key - entity['value'] = self.vreg.property_value(key) - return entity - - def form(self, keys, splitlabel=False): - buttons = [SubmitButton(), - Button(stdmsgs.BUTTON_CANCEL, cwaction='cancel')] - form = CompositeForm(self.req, domid=None, action=self.build_url(), - form_buttons=buttons, - submitmsg=self.req._('changes applied')) - path = self.req.relative_path() - if '?' in path: - path, params = path.split('?', 1) - form.form_add_hidden('__redirectparams', params) - form.form_add_hidden('__redirectpath', path) - for key in keys: - self.form_row(form, key, splitlabel) - return form.form_render(display_progress_div=False) - - def form_row(self, form, key, splitlabel): - entity = self.entity_for_key(key) - if splitlabel: - label = key.split('.')[-1] - else: - label = key - subform = EntityFieldsForm(self.req, entity=entity, set_error_url=False) - subform.append_field(PropertyValueField(name='value', label=label, - eidparam=True)) - subform.vreg = self.vreg - subform.form_add_hidden('pkey', key, eidparam=True) - form.form_add_subform(subform) - return subform - - -def is_user_prefs(cls, req, rset, row=None, col=0, **kwargs): - return req.user.eid == rset[row or 0][col] - - -class EPropertiesForm(SystemEPropertiesForm): - id = 'epropertiesform' - __select__ = ( - # we don't want guests to be able to come here - match_user_groups('users', 'managers') & - (none_rset() | ((one_line_rset() & is_user_prefs) & - (one_line_rset() & match_user_groups('managers')))) - ) - - title = _('preferences') - - @property - def user(self): - if self.rset is None: - return self.req.user - return self.rset.get_entity(self.row or 0, self.col or 0) - - @property - @cached - def eprops_rset(self): - return self.req.execute('Any P,K,V WHERE P is CWProperty, P pkey K, P value V,' - 'P for_user U, U eid %(x)s', {'x': self.user.eid}) - - def form_row(self, form, key, splitlabel): - subform = super(EPropertiesForm, self).form_row(form, key, splitlabel) - # if user is in the managers group and the property is being created, - # we have to set for_user explicitly - if not subform.edited_entity.has_eid() and self.user.matching_groups('managers'): - subform.form_add_hidden('for_user', self.user.eid, eidparam=True) - - -# eproperty form objects ###################################################### - -class PlaceHolderWidget(object): - - def render(self, form, field): - domid = form.context[field]['id'] - # empty span as well else html validation fail (label is refering to - # this id) - return '
%s
' % ( - domid, domid, form.req._('select a key first')) - - -class NotEditableWidget(object): - def __init__(self, value, msg=None): - self.value = value - self.msg = msg - - def render(self, form, field): - domid = form.context[field]['id'] - value = '%s' % (domid, self.value) - if self.msg: - value + '
%s
' % self.msg - return value - - -class PropertyKeyField(StringField): - """specific field for CWProperty.pkey to set the value widget according to - the selected key - """ - widget = Select - - def render(self, form, renderer): - wdg = self.get_widget(form) - wdg.attrs['tabindex'] = form.req.next_tabindex() - wdg.attrs['onchange'] = "javascript:setPropValueWidget('%s', %s)" % ( - form.edited_entity.eid, form.req.next_tabindex()) - return wdg.render(form, self) - - def vocabulary(self, form): - entity = form.edited_entity - _ = form.req._ - if entity.has_eid(): - return [(_(entity.pkey), entity.pkey)] - # key beginning with 'system.' should usually not be edited by hand - choices = entity.vreg.user_property_keys() - return [(u'', u'')] + sorted(zip((_(v) for v in choices), choices)) - - -class PropertyValueField(StringField): - """specific field for CWProperty.value which will be different according to - the selected key type and vocabulary information - """ - widget = PlaceHolderWidget - - def render(self, form, renderer=None, tabindex=None): - wdg = self.get_widget(form) - if tabindex is not None: - wdg.attrs['tabindex'] = tabindex - return wdg.render(form, self) - - def form_init(self, form): - entity = form.edited_entity - if not (entity.has_eid() or 'pkey' in entity): - # no key set yet, just include an empty div which will be filled - # on key selection - return - try: - pdef = form.vreg.property_info(entity.pkey) - except UnknownProperty, ex: - self.warning('%s (you should probably delete that property ' - 'from the database)', ex) - msg = form.req._('you should probably delete that property') - self.widget = NotEditableWidget(entity.printable_value('value'), - '%s (%s)' % (msg, ex)) - if entity.pkey.startswith('system.'): - msg = form.req._('value associated to this key is not editable ' - 'manually') - self.widget = NotEditableWidget(entity.printable_value('value'), msg) - # XXX race condition when used from CWPropertyForm, should not rely on - # instance attributes - self.initial = pdef['default'] - self.help = pdef['help'] - vocab = pdef['vocabulary'] - if vocab is not None: - if callable(vocab): - # list() just in case its a generator function - self.choices = list(vocab(form.req)) - else: - self.choices = vocab - wdg = Select() - else: - wdg = FIELDS[pdef['type']].widget() - if pdef['type'] == 'Boolean': - self.choices = [(form.req._('yes'), '1'), (form.req._('no'), '')] - elif pdef['type'] in ('Float', 'Int'): - wdg.attrs.setdefault('size', 3) - self.widget = wdg - -uicfg.rfields.set_rtag(PropertyKeyField, 'pkey', 'subject', 'CWProperty') -uicfg.rfields.set_rtag(PropertyValueField, 'value', 'subject', 'CWProperty') -