web/views/management.py
branchtls-sprint
changeset 691 35133d86970b
parent 688 cddfbdee0eb3
child 731 ac4a94e50b60
equal deleted inserted replaced
688:cddfbdee0eb3 691:35133d86970b
     7 """
     7 """
     8 __docformat__ = "restructuredtext en"
     8 __docformat__ = "restructuredtext en"
     9 
     9 
    10 from logilab.mtconverter import html_escape
    10 from logilab.mtconverter import html_escape
    11 
    11 
    12 from logilab.common.decorators import cached
    12 from cubicweb.selectors import yes, none_rset, match_user_groups
    13 
       
    14 from cubicweb.selectors import (yes, one_line_rset, none_rset,
       
    15                                 match_user_groups, chainfirst, chainall)
       
    16 from cubicweb.common.utils import UStringIO
       
    17 from cubicweb.common.view import AnyRsetView, StartupView, EntityView
    13 from cubicweb.common.view import AnyRsetView, StartupView, EntityView
    18 from cubicweb.common.uilib import html_traceback, rest_traceback
    14 from cubicweb.common.uilib import html_traceback, rest_traceback
    19 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
    15 from cubicweb.web import INTERNAL_FIELD_VALUE, eid_param, stdmsgs
    20 from cubicweb.web.widgets import StaticComboBoxWidget
    16 from cubicweb.web.widgets import StaticComboBoxWidget
    21 from cubicweb.web.form import FormMixIn
       
    22 
    17 
    23 _ = unicode
    18 _ = unicode
    24 
    19 
    25 def begin_form(w, entity, redirectvid, redirectpath=None, msg=None):
    20 def begin_form(w, entity, redirectvid, redirectpath=None, msg=None):
    26     w(u'<form method="post" action="%s">\n' % entity.req.build_url('edit'))
    21     w(u'<form method="post" action="%s">\n' % entity.req.build_url('edit'))
   148         _ = self.req._
   143         _ = self.req._
   149         newperm = self.vreg.etype_class('EPermission')(self.req, None)
   144         newperm = self.vreg.etype_class('EPermission')(self.req, None)
   150         newperm.eid = self.req.varmaker.next()
   145         newperm.eid = self.req.varmaker.next()
   151         w(u'<p>%s</p>' % _('add a new permission'))
   146         w(u'<p>%s</p>' % _('add a new permission'))
   152         begin_form(w, newperm, 'security', entity.rest_path())
   147         begin_form(w, newperm, 'security', entity.rest_path())
   153         w(u'<input type="hidden" name="%s" value="__cubicweb_internal_field__"/>'
   148         w(u'<input type="hidden" name="%s" value="%s"/>'
   154           % eid_param('edito-require_permission', newperm.eid))
   149           % (eid_param('edito-require_permission', newperm.eid), INTERNAL_FIELD_VALUE))
   155         w(u'<input type="hidden" name="%s" value="%s"/>'
   150         w(u'<input type="hidden" name="%s" value="%s"/>'
   156           % (eid_param('require_permission', newperm.eid), entity.eid))
   151           % (eid_param('require_permission', newperm.eid), entity.eid))
   157         w(u'<table border="0">\n')
   152         w(u'<table border="0">\n')
   158         w(u'<tr><th>%s</th><th>%s</th><th>%s</th><th>&nbsp;</th></tr>\n'
   153         w(u'<tr><th>%s</th><th>%s</th><th>%s</th><th>&nbsp;</th></tr>\n'
   159                % (_("name"), _("label"), _('granted to groups')))
   154                % (_("name"), _("label"), _('granted to groups')))
   177                 % self.req._(stdmsgs.BUTTON_OK))
   172                 % self.req._(stdmsgs.BUTTON_OK))
   178 
   173 
   179 
   174 
   180 class ErrorView(AnyRsetView):
   175 class ErrorView(AnyRsetView):
   181     """default view when no result has been found"""
   176     """default view when no result has been found"""
   182     __selectors__ = (yes,)
   177     __selectors__ = yes
   183     id = 'error'
   178     id = 'error'
   184 
   179 
   185     def page_title(self):
   180     def page_title(self):
   186         """returns a title according to the result set - used for the
   181         """returns a title according to the result set - used for the
   187         title in the HTML header
   182         title in the HTML header
   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