web/views/baseviews.py
branchtls-sprint
changeset 1451 982e8616d9a2
parent 1263 01152fffd593
child 1453 a9841184be7c
equal deleted inserted replaced
1450:8edb0806dde4 1451:982e8616d9a2
    38 
    38 
    39 class NoResultView(View):
    39 class NoResultView(View):
    40     """default view when no result has been found"""
    40     """default view when no result has been found"""
    41     __select__ = empty_rset()
    41     __select__ = empty_rset()
    42     id = 'noresult'
    42     id = 'noresult'
    43     
    43 
    44     def call(self, **kwargs):
    44     def call(self, **kwargs):
    45         self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
    45         self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
    46                % self.req._('No result matching query'))
    46                % self.req._('No result matching query'))
    47 
    47 
    48 
    48 
    49 class FinalView(AnyRsetView):
    49 class FinalView(AnyRsetView):
    50     """display values without any transformation (i.e. get a number for
    50     """display values without any transformation (i.e. get a number for
    51     entities) 
    51     entities)
    52     """
    52     """
    53     id = 'final'
    53     id = 'final'
    54     # record generated i18n catalog messages
    54     # record generated i18n catalog messages
    55     _('%d&nbsp;years')
    55     _('%d&nbsp;years')
    56     _('%d&nbsp;months')
    56     _('%d&nbsp;months')
    64     _('%d weeks')
    64     _('%d weeks')
    65     _('%d days')
    65     _('%d days')
    66     _('%d hours')
    66     _('%d hours')
    67     _('%d minutes')
    67     _('%d minutes')
    68     _('%d seconds')
    68     _('%d seconds')
    69             
    69 
    70     def cell_call(self, row, col, props=None, displaytime=False, format='text/html'):
    70     def cell_call(self, row, col, props=None, displaytime=False, format='text/html'):
    71         etype = self.rset.description[row][col]
    71         etype = self.rset.description[row][col]
    72         value = self.rset.rows[row][col]
    72         value = self.rset.rows[row][col]
    73         if etype == 'String':
    73         if etype == 'String':
    74             entity, rtype = self.rset.related_entity(row, col)
    74             entity, rtype = self.rset.related_entity(row, col)
    75             if entity is not None:
    75             if entity is not None:
    76                 # yes !
    76                 # yes !
    77                 self.w(entity.printable_value(rtype, value, format=format))
    77                 self.w(entity.printable_value(rtype, value, format=format))
    78                 return
    78                 return
    79         if etype in ('Time', 'Interval'):
    79         if etype in ('Time', 'Interval'):
    80             # value is DateTimeDelta but we have no idea about what is the 
    80             # value is DateTimeDelta but we have no idea about what is the
    81             # reference date here, so we can only approximate years and months
    81             # reference date here, so we can only approximate years and months
    82             if format == 'text/html':
    82             if format == 'text/html':
    83                 space = '&nbsp;'
    83                 space = '&nbsp;'
    84             else:
    84             else:
    85                 space = ' '
    85                 space = ' '
    98             else:
    98             else:
    99                 self.w(self.req.__('%%d%sseconds' % space) % int(value.seconds))
    99                 self.w(self.req.__('%%d%sseconds' % space) % int(value.seconds))
   100             return
   100             return
   101         self.wdata(printable_value(self.req, etype, value, props, displaytime=displaytime))
   101         self.wdata(printable_value(self.req, etype, value, props, displaytime=displaytime))
   102 
   102 
   103         
   103 
   104 PRIMARY_SKIP_RELS = set(['is', 'is_instance_of', 'identity',
   104 PRIMARY_SKIP_RELS = set(['is', 'is_instance_of', 'identity',
   105                          'owned_by', 'created_by', 
   105                          'owned_by', 'created_by',
   106                          'in_state', 'wf_info_for', 'require_permission',
   106                          'in_state', 'wf_info_for', 'require_permission',
   107                          'from_entity', 'to_entity',
   107                          'from_entity', 'to_entity',
   108                          'see_also'])
   108                          'see_also'])
   109 
   109 
   110 class PrimaryView(EntityView):
   110 class PrimaryView(EntityView):
   123         <head> and </head> of the returned page
   123         <head> and </head> of the returned page
   124 
   124 
   125         by default primary views are indexed
   125         by default primary views are indexed
   126         """
   126         """
   127         return []
   127         return []
   128     
   128 
   129     def cell_call(self, row, col):        
   129     def cell_call(self, row, col):
   130         self.row = row
   130         self.row = row
   131         # XXX move render_entity implementation here
   131         # XXX move render_entity implementation here
   132         self.render_entity(self.complete_entity(row, col))
   132         self.render_entity(self.complete_entity(row, col))
   133     
   133 
   134     def render_entity(self, entity):
   134     def render_entity(self, entity):
   135         """return html to display the given entity"""
   135         """return html to display the given entity"""
   136         siderelations = []
   136         siderelations = []
   137         self.render_entity_title(entity)
   137         self.render_entity_title(entity)
   138         self.render_entity_metadata(entity)
   138         self.render_entity_metadata(entity)
   148         self.w(u'</div>')
   148         self.w(u'</div>')
   149         # side boxes
   149         # side boxes
   150         self.w(u'<div class="primaryRight">')
   150         self.w(u'<div class="primaryRight">')
   151         self.render_side_related(entity, siderelations)
   151         self.render_side_related(entity, siderelations)
   152         self.w(u'</div>')
   152         self.w(u'</div>')
   153         self.w(u'<div class="clear"></div>')          
   153         self.w(u'<div class="clear"></div>')
   154         self.content_navigation_components('navcontentbottom')
   154         self.content_navigation_components('navcontentbottom')
   155 
   155 
   156     def content_navigation_components(self, context):
   156     def content_navigation_components(self, context):
   157         self.w(u'<div class="%s">' % context)
   157         self.w(u'<div class="%s">' % context)
   158         for comp in self.vreg.possible_vobjects('contentnavigation',
   158         for comp in self.vreg.possible_vobjects('contentnavigation',
   163             except NotImplementedError:
   163             except NotImplementedError:
   164                 warn('component %s doesnt implement cell_call, please update'
   164                 warn('component %s doesnt implement cell_call, please update'
   165                      % comp.__class__, DeprecationWarning)
   165                      % comp.__class__, DeprecationWarning)
   166                 comp.dispatch(w=self.w, view=self)
   166                 comp.dispatch(w=self.w, view=self)
   167         self.w(u'</div>')
   167         self.w(u'</div>')
   168         
   168 
   169     def iter_attributes(self, entity):
   169     def iter_attributes(self, entity):
   170         for rschema, targetschema in entity.e_schema.attribute_definitions():
   170         for rschema, targetschema in entity.e_schema.attribute_definitions():
   171             if rschema.type in self.skip_attrs:
   171             if rschema.type in self.skip_attrs:
   172                 continue
   172                 continue
   173             yield rschema, targetschema
   173             yield rschema, targetschema
   174             
   174 
   175     def iter_relations(self, entity):
   175     def iter_relations(self, entity):
   176         skip = set(self.skip_rels)
   176         skip = set(self.skip_rels)
   177         skip.update(PRIMARY_SKIP_RELS)
   177         skip.update(PRIMARY_SKIP_RELS)
   178         for rschema, targetschemas, x in entity.e_schema.relation_definitions():
   178         for rschema, targetschemas, x in entity.e_schema.relation_definitions():
   179             if rschema.type in skip:
   179             if rschema.type in skip:
   183     def render_entity_title(self, entity):
   183     def render_entity_title(self, entity):
   184         title = self.content_title(entity) # deprecate content_title?
   184         title = self.content_title(entity) # deprecate content_title?
   185         if title:
   185         if title:
   186             self.w(u'<h1><span class="etype">%s</span> %s</h1>'
   186             self.w(u'<h1><span class="etype">%s</span> %s</h1>'
   187                    % (entity.dc_type().capitalize(), title))
   187                    % (entity.dc_type().capitalize(), title))
   188     
   188 
   189     def content_title(self, entity):
   189     def content_title(self, entity):
   190         """default implementation return an empty string"""
   190         """default implementation return an empty string"""
   191         return u''
   191         return u''
   192             
   192 
   193     def render_entity_metadata(self, entity):
   193     def render_entity_metadata(self, entity):
   194         entity.view('metadata', w=self.w)
   194         entity.view('metadata', w=self.w)
   195         summary = self.summary(entity) # deprecate summary?
   195         summary = self.summary(entity) # deprecate summary?
   196         if summary:
   196         if summary:
   197             self.w(u'<div class="summary">%s</div>' % summary)
   197             self.w(u'<div class="summary">%s</div>' % summary)
   198     
   198 
   199     def summary(self, entity):
   199     def summary(self, entity):
   200         """default implementation return an empty string"""
   200         """default implementation return an empty string"""
   201         return u''    
   201         return u''
   202                
   202 
   203     def render_entity_attributes(self, entity, siderelations):
   203     def render_entity_attributes(self, entity, siderelations):
   204         for rschema, targetschema in self.iter_attributes(entity):
   204         for rschema, targetschema in self.iter_attributes(entity):
   205             attr = rschema.type
   205             attr = rschema.type
   206             if targetschema.type in ('Password', 'Bytes'):
   206             if targetschema.type in ('Password', 'Bytes'):
   207                 continue
   207                 continue
   261                 try:
   261                 try:
   262                     box.dispatch(w=self.w, row=self.row)
   262                     box.dispatch(w=self.w, row=self.row)
   263                 except NotImplementedError:
   263                 except NotImplementedError:
   264                     # much probably a context insensitive box, which only implements
   264                     # much probably a context insensitive box, which only implements
   265                     # .call() and not cell_call()
   265                     # .call() and not cell_call()
   266                     box.dispatch(w=self.w)               
   266                     box.dispatch(w=self.w)
   267                 
   267 
   268     def is_side_related(self, rschema, eschema):
   268     def is_side_related(self, rschema, eschema):
   269         return rschema.meta and \
   269         return rschema.meta and \
   270                not rschema.schema_relation() == eschema.schema_entity()
   270                not rschema.schema_relation() == eschema.schema_entity()
   271 
   271 
   272     def _render_related_entities(self, entity, rschema, related,
   272     def _render_related_entities(self, entity, rschema, related,
   296                                                     self.req._('see them all'))
   296                                                     self.req._('see them all'))
   297                 value +=  '</div>'
   297                 value +=  '</div>'
   298         label = display_name(self.req, rschema.type, role)
   298         label = display_name(self.req, rschema.type, role)
   299         self.field(label, value, show_label=show_label, w=self.w, tr=False)
   299         self.field(label, value, show_label=show_label, w=self.w, tr=False)
   300 
   300 
   301  
   301 
   302 class SecondaryView(EntityView):
   302 class SecondaryView(EntityView):
   303     id = 'secondary'
   303     id = 'secondary'
   304     title = _('secondary')
   304     title = _('secondary')
   305     
   305 
   306     def cell_call(self, row, col):
   306     def cell_call(self, row, col):
   307         """the secondary view for an entity
   307         """the secondary view for an entity
   308         secondary = icon + view(oneline)
   308         secondary = icon + view(oneline)
   309         """
   309         """
   310         entity = self.entity(row, col)
   310         entity = self.entity(row, col)
   312         self.wview('oneline', self.rset, row=row, col=col)
   312         self.wview('oneline', self.rset, row=row, col=col)
   313 
   313 
   314 
   314 
   315 class OneLineView(EntityView):
   315 class OneLineView(EntityView):
   316     id = 'oneline'
   316     id = 'oneline'
   317     title = _('oneline') 
   317     title = _('oneline')
   318 
   318 
   319     def cell_call(self, row, col):
   319     def cell_call(self, row, col):
   320         """the one line view for an entity: linked text view
   320         """the one line view for an entity: linked text view
   321         """
   321         """
   322         entity = self.entity(row, col)
   322         entity = self.entity(row, col)
   343             raise NotImplementedError, self
   343             raise NotImplementedError, self
   344         for i in xrange(len(rset)):
   344         for i in xrange(len(rset)):
   345             self.wview(self.id, rset, row=i, **kwargs)
   345             self.wview(self.id, rset, row=i, **kwargs)
   346             if len(rset) > 1:
   346             if len(rset) > 1:
   347                 self.w(u"\n")
   347                 self.w(u"\n")
   348     
   348 
   349     def cell_call(self, row, col=0, **kwargs):
   349     def cell_call(self, row, col=0, **kwargs):
   350         entity = self.entity(row, col)
   350         entity = self.entity(row, col)
   351         self.w(cut(entity.dc_title(),
   351         self.w(cut(entity.dc_title(),
   352                    self.req.property_value('navigation.short-line-size')))
   352                    self.req.property_value('navigation.short-line-size')))
   353 
   353 
   354 
   354 
   355 class MetaDataView(EntityView):
   355 class MetaDataView(EntityView):
   356     """paragraph view of some metadata"""
   356     """paragraph view of some metadata"""
   357     id = 'metadata'
   357     id = 'metadata'
   358     show_eid = True
   358     show_eid = True
   359     
   359 
   360     def cell_call(self, row, col):
   360     def cell_call(self, row, col):
   361         _ = self.req._
   361         _ = self.req._
   362         entity = self.entity(row, col)
   362         entity = self.entity(row, col)
   363         self.w(u'<div class="metadata">')
   363         self.w(u'<div class="metadata">')
   364         if self.show_eid:
   364         if self.show_eid:
   366         if entity.modification_date != entity.creation_date:
   366         if entity.modification_date != entity.creation_date:
   367             self.w(u'<span>%s</span> ' % _('latest update on'))
   367             self.w(u'<span>%s</span> ' % _('latest update on'))
   368             self.w(u'<span class="value">%s</span>,&nbsp;'
   368             self.w(u'<span class="value">%s</span>,&nbsp;'
   369                    % self.format_date(entity.modification_date))
   369                    % self.format_date(entity.modification_date))
   370         # entities from external source may not have a creation date (eg ldap)
   370         # entities from external source may not have a creation date (eg ldap)
   371         if entity.creation_date: 
   371         if entity.creation_date:
   372             self.w(u'<span>%s</span> ' % _('created on'))
   372             self.w(u'<span>%s</span> ' % _('created on'))
   373             self.w(u'<span class="value">%s</span>'
   373             self.w(u'<span class="value">%s</span>'
   374                    % self.format_date(entity.creation_date))
   374                    % self.format_date(entity.creation_date))
   375         if entity.creator:
   375         if entity.creator:
   376             self.w(u'&nbsp;<span>%s</span> ' % _('by'))
   376             self.w(u'&nbsp;<span>%s</span> ' % _('by'))
   406         self.w(u'<a href="%s" title="%s">' % (html_escape(entity.absolute_url()),
   406         self.w(u'<a href="%s" title="%s">' % (html_escape(entity.absolute_url()),
   407                                               html_escape(desc)))
   407                                               html_escape(desc)))
   408         self.w(html_escape(self.view('textincontext', self.rset, row=row, col=col)))
   408         self.w(html_escape(self.view('textincontext', self.rset, row=row, col=col)))
   409         self.w(u'</a>')
   409         self.w(u'</a>')
   410 
   410 
   411         
   411 
   412 class OutOfContextView(EntityView):
   412 class OutOfContextView(EntityView):
   413     id = 'outofcontext'
   413     id = 'outofcontext'
   414 
   414 
   415     def cell_call(self, row, col):
   415     def cell_call(self, row, col):
   416         self.w(u'<a href="%s">' % self.entity(row, col).absolute_url())
   416         self.w(u'<a href="%s">' % self.entity(row, col).absolute_url())
   417         self.w(html_escape(self.view('textoutofcontext', self.rset, row=row, col=col)))
   417         self.w(html_escape(self.view('textoutofcontext', self.rset, row=row, col=col)))
   418         self.w(u'</a>')
   418         self.w(u'</a>')
   419 
   419 
   420             
   420 
   421 # list views ##################################################################
   421 # list views ##################################################################
   422     
   422 
   423 class ListView(EntityView):
   423 class ListView(EntityView):
   424     id = 'list'
   424     id = 'list'
   425     title = _('list')
   425     title = _('list')
   426     item_vid = 'listitem'
   426     item_vid = 'listitem'
   427         
   427 
   428     def call(self, klass=None, title=None, subvid=None, listid=None, **kwargs):
   428     def call(self, klass=None, title=None, subvid=None, listid=None, **kwargs):
   429         """display a list of entities by calling their <item_vid> view
   429         """display a list of entities by calling their <item_vid> view
   430         
   430 
   431         :param listid: the DOM id to use for the root element
   431         :param listid: the DOM id to use for the root element
   432         """
   432         """
   433         if subvid is None and 'subvid' in self.req.form:
   433         if subvid is None and 'subvid' in self.req.form:
   434             subvid = self.req.form.pop('subvid') # consume it
   434             subvid = self.req.form.pop('subvid') # consume it
   435         if listid:
   435         if listid:
   472         if len(self.rset) == 1:
   472         if len(self.rset) == 1:
   473             entity = self.rset.get_entity(0, 0)
   473             entity = self.rset.get_entity(0, 0)
   474             return self.build_url(entity.rest_path(), vid=self.id)
   474             return self.build_url(entity.rest_path(), vid=self.id)
   475         return self.build_url(rql=self.rset.printable_rql(), vid=self.id)
   475         return self.build_url(rql=self.rset.printable_rql(), vid=self.id)
   476 
   476 
   477  
   477 
   478 class ListItemView(EntityView):
   478 class ListItemView(EntityView):
   479     id = 'listitem'
   479     id = 'listitem'
   480     
   480 
   481     @property
   481     @property
   482     def redirect_vid(self):
   482     def redirect_vid(self):
   483         if self.req.search_state[0] == 'normal':
   483         if self.req.search_state[0] == 'normal':
   484             return 'outofcontext'
   484             return 'outofcontext'
   485         return 'outofcontext-search'
   485         return 'outofcontext-search'
   486         
   486 
   487     def cell_call(self, row, col, vid=None, **kwargs):
   487     def cell_call(self, row, col, vid=None, **kwargs):
   488         if not vid:
   488         if not vid:
   489             vid = self.redirect_vid
   489             vid = self.redirect_vid
   490         try:
   490         try:
   491             self.wview(vid, self.rset, row=row, col=col, **kwargs)
   491             self.wview(vid, self.rset, row=row, col=col, **kwargs)
   502 
   502 
   503 
   503 
   504 class CSVView(SimpleListView):
   504 class CSVView(SimpleListView):
   505     id = 'csv'
   505     id = 'csv'
   506     redirect_vid = 'incontext'
   506     redirect_vid = 'incontext'
   507         
   507 
   508     def call(self, **kwargs):
   508     def call(self, **kwargs):
   509         rset = self.rset
   509         rset = self.rset
   510         for i in xrange(len(rset)):
   510         for i in xrange(len(rset)):
   511             self.cell_call(i, 0, vid=kwargs.get('vid'))
   511             self.cell_call(i, 0, vid=kwargs.get('vid'))
   512             if i < rset.rowcount-1:
   512             if i < rset.rowcount-1:
   513                 self.w(u", ")
   513                 self.w(u", ")
   514 
   514 
   515 
   515 
   516 class TreeItemView(ListItemView):
   516 class TreeItemView(ListItemView):
   517     id = 'treeitem'
   517     id = 'treeitem'
   518     
   518 
   519     def cell_call(self, row, col):
   519     def cell_call(self, row, col):
   520         self.wview('incontext', self.rset, row=row, col=col)
   520         self.wview('incontext', self.rset, row=row, col=col)
   521 
   521 
   522 
   522 
   523 class TextSearchResultView(EntityView):
   523 class TextSearchResultView(EntityView):
   550                     if len(ctx) > 30:
   550                     if len(ctx) > 30:
   551                         contexts.append(u'...' + ctx[-30:])
   551                         contexts.append(u'...' + ctx[-30:])
   552                     else:
   552                     else:
   553                         contexts.append(ctx)
   553                         contexts.append(ctx)
   554                 value = u'\n' + highlighted.join(contexts)
   554                 value = u'\n' + highlighted.join(contexts)
   555                 self.w(value.replace('\n', '<br/>'))            
   555                 self.w(value.replace('\n', '<br/>'))
   556 
   556 
   557 
   557 
   558 class TooltipView(EntityView):
   558 class TooltipView(EntityView):
   559     """A entity view used in a tooltip"""
   559     """A entity view used in a tooltip"""
   560     id = 'tooltip'
   560     id = 'tooltip'
   577 XmlView = class_moved(xmlrss.XmlView)
   577 XmlView = class_moved(xmlrss.XmlView)
   578 XmlItemView = class_moved(xmlrss.XmlItemView)
   578 XmlItemView = class_moved(xmlrss.XmlItemView)
   579 XmlRsetView = class_moved(xmlrss.XmlRsetView)
   579 XmlRsetView = class_moved(xmlrss.XmlRsetView)
   580 RssView = class_moved(xmlrss.RssView)
   580 RssView = class_moved(xmlrss.RssView)
   581 RssItemView = class_moved(xmlrss.RssItemView)
   581 RssItemView = class_moved(xmlrss.RssItemView)
   582             
   582