web/views/baseviews.py
changeset 3451 6b46d73823f5
parent 3418 7b49fa7e942d
child 3720 5376aaadd16b
equal deleted inserted replaced
3448:495862266785 3451:6b46d73823f5
    42     __select__ = empty_rset()
    42     __select__ = empty_rset()
    43     __regid__ = 'noresult'
    43     __regid__ = 'noresult'
    44 
    44 
    45     def call(self, **kwargs):
    45     def call(self, **kwargs):
    46         self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
    46         self.w(u'<div class="searchMessage"><strong>%s</strong></div>\n'
    47                % self.req._('No result matching query'))
    47                % self._cw._('No result matching query'))
    48 
    48 
    49 
    49 
    50 class FinalView(AnyRsetView):
    50 class FinalView(AnyRsetView):
    51     """display values without any transformation (i.e. get a number for
    51     """display values without any transformation (i.e. get a number for
    52     entities)
    52     entities)
    67     _('%d hours')
    67     _('%d hours')
    68     _('%d minutes')
    68     _('%d minutes')
    69     _('%d seconds')
    69     _('%d seconds')
    70 
    70 
    71     def cell_call(self, row, col, props=None, format='text/html'):
    71     def cell_call(self, row, col, props=None, format='text/html'):
    72         etype = self.rset.description[row][col]
    72         etype = self.cw_rset.description[row][col]
    73         value = self.rset.rows[row][col]
    73         value = self.cw_rset.rows[row][col]
    74 
    74 
    75         if etype == 'String':
    75         if etype == 'String':
    76             entity, rtype = self.rset.related_entity(row, col)
    76             entity, rtype = self.cw_rset.related_entity(row, col)
    77             if entity is not None:
    77             if entity is not None:
    78                 # yes !
    78                 # yes !
    79                 self.w(entity.printable_value(rtype, value, format=format))
    79                 self.w(entity.printable_value(rtype, value, format=format))
    80                 return
    80                 return
    81         if etype in ('Time', 'Interval'):
    81         if etype in ('Time', 'Interval'):
    91             if format == 'text/html':
    91             if format == 'text/html':
    92                 space = '&#160;'
    92                 space = '&#160;'
    93             else:
    93             else:
    94                 space = ' '
    94                 space = ' '
    95             if value.days > 730: # 2 years
    95             if value.days > 730: # 2 years
    96                 self.w(self.req.__('%%d%syears' % space) % (value.days // 365))
    96                 self.w(self._cw.__('%%d%syears' % space) % (value.days // 365))
    97             elif value.days > 60: # 2 months
    97             elif value.days > 60: # 2 months
    98                 self.w(self.req.__('%%d%smonths' % space) % (value.days // 30))
    98                 self.w(self._cw.__('%%d%smonths' % space) % (value.days // 30))
    99             elif value.days > 14: # 2 weeks
    99             elif value.days > 14: # 2 weeks
   100                 self.w(self.req.__('%%d%sweeks' % space) % (value.days // 7))
   100                 self.w(self._cw.__('%%d%sweeks' % space) % (value.days // 7))
   101             elif value.days > 2:
   101             elif value.days > 2:
   102                 self.w(self.req.__('%%d%sdays' % space) % int(value.days))
   102                 self.w(self._cw.__('%%d%sdays' % space) % int(value.days))
   103             elif value.seconds > 3600:
   103             elif value.seconds > 3600:
   104                 self.w(self.req.__('%%d%shours' % space) % int(value.seconds // 3600))
   104                 self.w(self._cw.__('%%d%shours' % space) % int(value.seconds // 3600))
   105             elif value.seconds >= 120:
   105             elif value.seconds >= 120:
   106                 self.w(self.req.__('%%d%sminutes' % space) % int(value.seconds // 60))
   106                 self.w(self._cw.__('%%d%sminutes' % space) % int(value.seconds // 60))
   107             else:
   107             else:
   108                 self.w(self.req.__('%%d%sseconds' % space) % int(value.seconds))
   108                 self.w(self._cw.__('%%d%sseconds' % space) % int(value.seconds))
   109             return
   109             return
   110         self.wdata(printable_value(self.req, etype, value, props))
   110         self.wdata(printable_value(self._cw, etype, value, props))
   111 
   111 
   112 
   112 
   113 # XXX deprecated
   113 # XXX deprecated
   114 class SecondaryView(EntityView):
   114 class SecondaryView(EntityView):
   115     __regid__ = 'secondary'
   115     __regid__ = 'secondary'
   117 
   117 
   118     def cell_call(self, row, col):
   118     def cell_call(self, row, col):
   119         """the secondary view for an entity
   119         """the secondary view for an entity
   120         secondary = icon + view(oneline)
   120         secondary = icon + view(oneline)
   121         """
   121         """
   122         entity = self.rset.get_entity(row, col)
   122         entity = self.cw_rset.get_entity(row, col)
   123         self.w(u'&#160;')
   123         self.w(u'&#160;')
   124         self.wview('oneline', self.rset, row=row, col=col)
   124         self.wview('oneline', self.cw_rset, row=row, col=col)
   125 
   125 
   126 
   126 
   127 class OneLineView(EntityView):
   127 class OneLineView(EntityView):
   128     __regid__ = 'oneline'
   128     __regid__ = 'oneline'
   129     title = _('oneline')
   129     title = _('oneline')
   130 
   130 
   131     def cell_call(self, row, col):
   131     def cell_call(self, row, col):
   132         """the one line view for an entity: linked text view
   132         """the one line view for an entity: linked text view
   133         """
   133         """
   134         entity = self.rset.get_entity(row, col)
   134         entity = self.cw_rset.get_entity(row, col)
   135         self.w(u'<a href="%s">' % xml_escape(entity.absolute_url()))
   135         self.w(u'<a href="%s">' % xml_escape(entity.absolute_url()))
   136         self.w(xml_escape(self.view('text', self.rset, row=row, col=col)))
   136         self.w(xml_escape(self._cw.view('text', self.cw_rset, row=row, col=col)))
   137         self.w(u'</a>')
   137         self.w(u'</a>')
   138 
   138 
   139 
   139 
   140 class TextView(EntityView):
   140 class TextView(EntityView):
   141     """the simplest text view for an entity"""
   141     """the simplest text view for an entity"""
   148         other rows of the result set and call the same view on the
   148         other rows of the result set and call the same view on the
   149         particular row
   149         particular row
   150 
   150 
   151         Views applicable on None result sets have to override this method
   151         Views applicable on None result sets have to override this method
   152         """
   152         """
   153         rset = self.rset
   153         rset = self.cw_rset
   154         if rset is None:
   154         if rset is None:
   155             raise NotImplementedError, self
   155             raise NotImplementedError, self
   156         for i in xrange(len(rset)):
   156         for i in xrange(len(rset)):
   157             self.wview(self.id, rset, row=i, **kwargs)
   157             self.wview(self.__regid__, rset, row=i, **kwargs)
   158             if len(rset) > 1:
   158             if len(rset) > 1:
   159                 self.w(u"\n")
   159                 self.w(u"\n")
   160 
   160 
   161     def cell_call(self, row, col=0, **kwargs):
   161     def cell_call(self, row, col=0, **kwargs):
   162         entity = self.cw_rset.get_entity(row, col)
   162         entity = self.cw_rset.get_entity(row, col)
   168     """paragraph view of some metadata"""
   168     """paragraph view of some metadata"""
   169     __regid__ = 'metadata'
   169     __regid__ = 'metadata'
   170     show_eid = True
   170     show_eid = True
   171 
   171 
   172     def cell_call(self, row, col):
   172     def cell_call(self, row, col):
   173         _ = self.req._
   173         _ = self._cw._
   174         entity = self.rset.get_entity(row, col)
   174         entity = self.cw_rset.get_entity(row, col)
   175         self.w(u'<div class="metadata">')
   175         self.w(u'<div class="metadata">')
   176         if self.show_eid:
   176         if self.show_eid:
   177             self.w(u'#%s - ' % entity.eid)
   177             self.w(u'#%s - ' % entity.eid)
   178         if entity.modification_date != entity.creation_date:
   178         if entity.modification_date != entity.creation_date:
   179             self.w(u'<span>%s</span> ' % _('latest update on'))
   179             self.w(u'<span>%s</span> ' % _('latest update on'))
   180             self.w(u'<span class="value">%s</span>, '
   180             self.w(u'<span class="value">%s</span>, '
   181                    % self.format_date(entity.modification_date))
   181                    % self._cw.format_date(entity.modification_date))
   182         # entities from external source may not have a creation date (eg ldap)
   182         # entities from external source may not have a creation date (eg ldap)
   183         if entity.creation_date:
   183         if entity.creation_date:
   184             self.w(u'<span>%s</span> ' % _('created on'))
   184             self.w(u'<span>%s</span> ' % _('created on'))
   185             self.w(u'<span class="value">%s</span>'
   185             self.w(u'<span class="value">%s</span>'
   186                    % self.format_date(entity.creation_date))
   186                    % self._cw.format_date(entity.creation_date))
   187         if entity.creator:
   187         if entity.creator:
   188             self.w(u' <span>%s</span> ' % _('by'))
   188             self.w(u' <span>%s</span> ' % _('by'))
   189             self.w(u'<span class="value">%s</span>' % entity.creator.name())
   189             self.w(u'<span class="value">%s</span>' % entity.creator.name())
   190         self.w(u'</div>')
   190         self.w(u'</div>')
   191 
   191 
   192 
   192 
   193 class InContextTextView(TextView):
   193 class InContextTextView(TextView):
   194     __regid__ = 'textincontext'
   194     __regid__ = 'textincontext'
   195     title = None # not listed as a possible view
   195     title = None # not listed as a possible view
   196     def cell_call(self, row, col):
   196     def cell_call(self, row, col):
   197         entity = self.rset.get_entity(row, col)
   197         entity = self.cw_rset.get_entity(row, col)
   198         self.w(entity.dc_title())
   198         self.w(entity.dc_title())
   199 
   199 
   200 
   200 
   201 class OutOfContextTextView(InContextTextView):
   201 class OutOfContextTextView(InContextTextView):
   202     __regid__ = 'textoutofcontext'
   202     __regid__ = 'textoutofcontext'
   203 
   203 
   204     def cell_call(self, row, col):
   204     def cell_call(self, row, col):
   205         entity = self.rset.get_entity(row, col)
   205         entity = self.cw_rset.get_entity(row, col)
   206         self.w(entity.dc_long_title())
   206         self.w(entity.dc_long_title())
   207 
   207 
   208 
   208 
   209 class InContextView(EntityView):
   209 class InContextView(EntityView):
   210     __regid__ = 'incontext'
   210     __regid__ = 'incontext'
   211 
   211 
   212     def cell_call(self, row, col):
   212     def cell_call(self, row, col):
   213         entity = self.rset.get_entity(row, col)
   213         entity = self.cw_rset.get_entity(row, col)
   214         desc = cut(entity.dc_description(), 50)
   214         desc = cut(entity.dc_description(), 50)
   215         self.w(u'<a href="%s" title="%s">' % (
   215         self.w(u'<a href="%s" title="%s">' % (
   216             xml_escape(entity.absolute_url()), xml_escape(desc)))
   216             xml_escape(entity.absolute_url()), xml_escape(desc)))
   217         self.w(xml_escape(self.view('textincontext', self.rset,
   217         self.w(xml_escape(self._cw.view('textincontext', self.cw_rset,
   218                                      row=row, col=col)))
   218                                         row=row, col=col)))
   219         self.w(u'</a>')
   219         self.w(u'</a>')
   220 
   220 
   221 
   221 
   222 class OutOfContextView(EntityView):
   222 class OutOfContextView(EntityView):
   223     __regid__ = 'outofcontext'
   223     __regid__ = 'outofcontext'
   224 
   224 
   225     def cell_call(self, row, col):
   225     def cell_call(self, row, col):
   226         entity = self.rset.get_entity(row, col)
   226         entity = self.cw_rset.get_entity(row, col)
   227         desc = cut(entity.dc_description(), 50)
   227         desc = cut(entity.dc_description(), 50)
   228         self.w(u'<a href="%s" title="%s">' % (
   228         self.w(u'<a href="%s" title="%s">' % (
   229             xml_escape(entity.absolute_url()), xml_escape(desc)))
   229             xml_escape(entity.absolute_url()), xml_escape(desc)))
   230         self.w(xml_escape(self.view('textoutofcontext', self.rset,
   230         self.w(xml_escape(self._cw.view('textoutofcontext', self.cw_rset,
   231                                      row=row, col=col)))
   231                                         row=row, col=col)))
   232         self.w(u'</a>')
   232         self.w(u'</a>')
   233 
   233 
   234 
   234 
   235 # list views ##################################################################
   235 # list views ##################################################################
   236 
   236 
   243         """display a list of entities by calling their <item_vid> view
   243         """display a list of entities by calling their <item_vid> view
   244 
   244 
   245         :param listid: the DOM id to use for the root element
   245         :param listid: the DOM id to use for the root element
   246         """
   246         """
   247         # XXX much of the behaviour here should probably be outside this view
   247         # XXX much of the behaviour here should probably be outside this view
   248         if subvid is None and 'subvid' in self.req.form:
   248         if subvid is None and 'subvid' in self._cw.form:
   249             subvid = self.req.form.pop('subvid') # consume it
   249             subvid = self._cw.form.pop('subvid') # consume it
   250         if listid:
   250         if listid:
   251             listid = u' id="%s"' % listid
   251             listid = u' id="%s"' % listid
   252         else:
   252         else:
   253             listid = u''
   253             listid = u''
   254         if title:
   254         if title:
   255             self.w(u'<div%s class="%s"><h4>%s</h4>\n' % (listid, klass or 'section', title))
   255             self.w(u'<div%s class="%s"><h4>%s</h4>\n' % (listid, klass or 'section', title))
   256             self.w(u'<ul>\n')
   256             self.w(u'<ul>\n')
   257         else:
   257         else:
   258             self.w(u'<ul%s class="%s">\n' % (listid, klass or 'section'))
   258             self.w(u'<ul%s class="%s">\n' % (listid, klass or 'section'))
   259         for i in xrange(self.rset.rowcount):
   259         for i in xrange(self.cw_rset.rowcount):
   260             self.cell_call(row=i, col=0, vid=subvid, **kwargs)
   260             self.cell_call(row=i, col=0, vid=subvid, **kwargs)
   261         self.w(u'</ul>\n')
   261         self.w(u'</ul>\n')
   262         if title:
   262         if title:
   263             self.w(u'</div>\n')
   263             self.w(u'</div>\n')
   264 
   264 
   265     def cell_call(self, row, col=0, vid=None, **kwargs):
   265     def cell_call(self, row, col=0, vid=None, **kwargs):
   266         self.w(u'<li>')
   266         self.w(u'<li>')
   267         self.wview(self.item_vid, self.rset, row=row, col=col, vid=vid, **kwargs)
   267         self.wview(self.item_vid, self.cw_rset, row=row, col=col, vid=vid, **kwargs)
   268         self.w(u'</li>\n')
   268         self.w(u'</li>\n')
   269 
   269 
   270 
   270 
   271 class ListItemView(EntityView):
   271 class ListItemView(EntityView):
   272     __regid__ = 'listitem'
   272     __regid__ = 'listitem'
   273 
   273 
   274     @property
   274     @property
   275     def redirect_vid(self):
   275     def redirect_vid(self):
   276         if self.req.search_state[0] == 'normal':
   276         if self._cw.search_state[0] == 'normal':
   277             return 'outofcontext'
   277             return 'outofcontext'
   278         return 'outofcontext-search'
   278         return 'outofcontext-search'
   279 
   279 
   280     def cell_call(self, row, col, vid=None, **kwargs):
   280     def cell_call(self, row, col, vid=None, **kwargs):
   281         if not vid:
   281         if not vid:
   282             vid = self.redirect_vid
   282             vid = self.redirect_vid
   283         try:
   283         try:
   284             self.wview(vid, self.rset, row=row, col=col, **kwargs)
   284             self.wview(vid, self.cw_rset, row=row, col=col, **kwargs)
   285         except NoSelectableObject:
   285         except NoSelectableObject:
   286             if vid == self.redirect_vid:
   286             if vid == self.redirect_vid:
   287                 raise
   287                 raise
   288             self.wview(self.redirect_vid, self.rset, row=row, col=col, **kwargs)
   288             self.wview(self.redirect_vid, self.cw_rset, row=row, col=col, **kwargs)
   289 
   289 
   290 
   290 
   291 class SimpleListView(ListItemView):
   291 class SimpleListView(ListItemView):
   292     """list without bullets"""
   292     """list without bullets"""
   293     __regid__ = 'simplelist'
   293     __regid__ = 'simplelist'
   300     __select__ = EntityView.__select__ & one_etype_rset()
   300     __select__ = EntityView.__select__ & one_etype_rset()
   301     item_vid = 'adaptedlistitem'
   301     item_vid = 'adaptedlistitem'
   302 
   302 
   303     @property
   303     @property
   304     def title(self):
   304     def title(self):
   305         etype = iter(self.rset.column_types(0)).next()
   305         etype = iter(self.cw_rset.column_types(0)).next()
   306         return display_name(self.req, etype, form='plural')
   306         return display_name(self._cw, etype, form='plural')
   307 
   307 
   308     def call(self, **kwargs):
   308     def call(self, **kwargs):
   309         """display a list of entities by calling their <item_vid> view"""
   309         """display a list of entities by calling their <item_vid> view"""
   310         if not 'vtitle' in self.req.form:
   310         if not 'vtitle' in self._cw.form:
   311             self.w(u'<h1>%s</h1>' % self.title)
   311             self.w(u'<h1>%s</h1>' % self.title)
   312         super(AdaptedListView, self).call(**kwargs)
   312         super(AdaptedListView, self).call(**kwargs)
   313 
   313 
   314     def cell_call(self, row, col=0, vid=None, **kwargs):
   314     def cell_call(self, row, col=0, vid=None, **kwargs):
   315         self.wview(self.item_vid, self.rset, row=row, col=col, vid=vid, **kwargs)
   315         self.wview(self.item_vid, self.cw_rset, row=row, col=col, vid=vid, **kwargs)
   316 
   316 
   317 
   317 
   318 class AdaptedListItemView(ListItemView):
   318 class AdaptedListItemView(ListItemView):
   319     __regid__ = 'adaptedlistitem'
   319     __regid__ = 'adaptedlistitem'
   320 
   320 
   322 class CSVView(SimpleListView):
   322 class CSVView(SimpleListView):
   323     __regid__ = 'csv'
   323     __regid__ = 'csv'
   324     redirect_vid = 'incontext'
   324     redirect_vid = 'incontext'
   325 
   325 
   326     def call(self, **kwargs):
   326     def call(self, **kwargs):
   327         rset = self.rset
   327         rset = self.cw_rset
   328         for i in xrange(len(rset)):
   328         for i in xrange(len(rset)):
   329             self.cell_call(i, 0, vid=kwargs.get('vid'))
   329             self.cell_call(i, 0, vid=kwargs.get('vid'))
   330             if i < rset.rowcount-1:
   330             if i < rset.rowcount-1:
   331                 self.w(u", ")
   331                 self.w(u", ")
   332 
   332 
   333 
   333 
   334 class TreeItemView(ListItemView):
   334 class TreeItemView(ListItemView):
   335     __regid__ = 'treeitem'
   335     __regid__ = 'treeitem'
   336 
   336 
   337     def cell_call(self, row, col):
   337     def cell_call(self, row, col):
   338         self.wview('incontext', self.rset, row=row, col=col)
   338         self.wview('incontext', self.cw_rset, row=row, col=col)
   339 
   339 
   340 class TextSearchResultView(EntityView):
   340 class TextSearchResultView(EntityView):
   341     """this view is used to display full-text search
   341     """this view is used to display full-text search
   342 
   342 
   343     It tries to highlight part of data where the search word appears.
   343     It tries to highlight part of data where the search word appears.
   345     XXX: finish me (fixed line width, fixed number of lines, CSS, etc.)
   345     XXX: finish me (fixed line width, fixed number of lines, CSS, etc.)
   346     """
   346     """
   347     __regid__ = 'tsearch'
   347     __regid__ = 'tsearch'
   348 
   348 
   349     def cell_call(self, row, col, **kwargs):
   349     def cell_call(self, row, col, **kwargs):
   350         entity = self.complete_entity(row, col)
   350         entity = self.cw_rset.complete_entity(row, col)
   351         self.w(entity.view('incontext'))
   351         self.w(entity.view('incontext'))
   352         searched = self.rset.searched_text()
   352         searched = self.cw_rset.searched_text()
   353         if searched is None:
   353         if searched is None:
   354             return
   354             return
   355         searched = searched.lower()
   355         searched = searched.lower()
   356         highlighted = '<b>%s</b>' % searched
   356         highlighted = '<b>%s</b>' % searched
   357         for attr in entity.e_schema.indexable_attributes():
   357         for attr in entity.e_schema.indexable_attributes():
   374 
   374 
   375 class TooltipView(EntityView):
   375 class TooltipView(EntityView):
   376     """A entity view used in a tooltip"""
   376     """A entity view used in a tooltip"""
   377     __regid__ = 'tooltip'
   377     __regid__ = 'tooltip'
   378     def cell_call(self, row, col):
   378     def cell_call(self, row, col):
   379         self.wview('oneline', self.rset, row=row, col=col)
   379         self.wview('oneline', self.cw_rset, row=row, col=col)
   380 
   380 
   381 
   381 
   382 # XXX bw compat
   382 # XXX bw compat
   383 
   383 
   384 from logilab.common.deprecation import class_moved
   384 from logilab.common.deprecation import class_moved