diff -r 000000000000 -r b97547f5f1fa web/views/iprogress.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/views/iprogress.py Wed Nov 05 15:52:50 2008 +0100 @@ -0,0 +1,195 @@ +"""Specific views for entities implementing IProgress + +:organization: Logilab +:copyright: 2001-2008 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 cubicweb.interfaces import IProgress, IMileStone +from cubicweb.schema import display_name +from cubicweb.common.view import EntityView +from cubicweb.common.selectors import interface_selector, accept_selector +from cubicweb.web.htmlwidgets import ProgressBarWidget + + +class ProgressTableView(EntityView): + """The progress table view is able to display progress information + of any object implement IMileStone. + + The default layout is composoed of 7 columns : parent task, + milestone, state, estimated date, cost, progressbar, and todo_by + + The view accepts an optional ``columns`` paramater that lets you + remove or reorder some of those columns. + + To add new columns, you should extend this class, define a new + ``columns`` class attribute and implement corresponding + build_COLNAME_cell methods + + header_for_COLNAME methods allow to customize header's label + """ + + id = 'progress_table_view' + title = _('task progression') + __selectors__ = (accept_selector, interface_selector) + + accepts_interfaces = (IMileStone,) + + # default columns of the table + columns = (_('project'), _('milestone'), _('state'), _('eta_date'), + _('cost'), _('progress'), _('todo_by')) + + + def call(self, columns=None): + """displays all versions in a table""" + self.req.add_css('cubicweb.iprogress.css') + _ = self.req._ + self.columns = columns or self.columns + ecls = self.vreg.etype_class(self.rset.description[0][0]) + self.w(u'') + self.table_header(ecls) + self.w(u'') + for row in xrange(self.rset.rowcount): + self.cell_call(row=row, col=0) + self.w(u'') + self.w(u'
') + + def cell_call(self, row, col): + _ = self.req._ + entity = self.entity(row, col) + infos = {} + for col in self.columns: + meth = getattr(self, 'build_%s_cell' % col, None) + # find the build method or try to find matching attribute + if meth: + content = meth(entity) + else: + content = entity.printable_value(col) + infos[col] = content + if hasattr(entity, 'progress_class'): + cssclass = entity.progress_class() + else: + cssclass = u'' + self.w(u"""""" % cssclass) + line = u''.join(u'%%(%s)s' % col for col in self.columns) + self.w(line % infos) + self.w(u'\n') + + ## header management ###################################################### + + def header_for_project(self, ecls): + """use entity's parent type as label""" + return display_name(self.req, ecls.parent_type) + + def header_for_milestone(self, ecls): + """use entity's type as label""" + return display_name(self.req, ecls.id) + + def table_header(self, ecls): + """builds the table's header""" + self.w(u'') + _ = self.req._ + for column in self.columns: + meth = getattr(self, 'header_for_%s' % column, None) + if meth: + colname = meth(ecls) + else: + colname = _(column) + self.w(u'%s' % html_escape(colname)) + self.w(u'\n') + + + ## cell management ######################################################## + def build_project_cell(self, entity): + """``project`` column cell renderer""" + project = entity.get_main_task() + if project: + return project.view('incontext') + return self.req._('no related project') + + def build_milestone_cell(self, entity): + """``milestone`` column cell renderer""" + return entity.view('incontext') + + def build_state_cell(self, entity): + """``state`` column cell renderer""" + return html_escape(self.req._(entity.state)) + + def build_eta_date_cell(self, entity): + """``eta_date`` column cell renderer""" + if entity.finished(): + return self.format_date(entity.completion_date()) + formated_date = self.format_date(entity.initial_prevision_date()) + if entity.in_progress(): + eta_date = self.format_date(entity.eta_date()) + _ = self.req._ + if formated_date: + formated_date += u' (%s %s)' % (_('expected:'), eta_date) + else: + formated_date = u'%s %s' % (_('expected:'), eta_date) + return formated_date + + def build_todo_by_cell(self, entity): + """``todo_by`` column cell renderer""" + return u', '.join(p.view('outofcontext') for p in entity.contractors()) + + def build_cost_cell(self, entity): + """``cost`` column cell renderer""" + _ = self.req._ + pinfo = entity.progress_info() + totalcost = pinfo.get('estimatedcorrected', pinfo['estimated']) + missing = pinfo.get('notestimatedcorrected', pinfo.get('notestimated', 0)) + costdescr = [] + if missing: + # XXX: link to unestimated entities + costdescr.append(_('%s not estimated') % missing) + estimated = pinfo['estimated'] + if estimated and estimated != totalcost: + costdescr.append(_('initial estimation %s') % estimated) + if costdescr: + return u'%s (%s)' % (totalcost, ', '.join(costdescr)) + return unicode(totalcost) + + def build_progress_cell(self, entity): + """``progress`` column cell renderer""" + progress = u'
%s (%.2f%%)
' % ( + entity.done, entity.progress()) + return progress + entity.view('progressbar') + + +class InContextProgressTableView(ProgressTableView): + """this views redirects to ``progress_table_view`` but removes + the ``project`` column + """ + id = 'ic_progress_table_view' + + def call(self): + view = self.vreg.select_view('progress_table_view', self.req, self.rset) + columns = list(view.columns) + try: + columns.remove('project') + except ValueError: + self.info('[ic_progress_table_view] could not remove project from columns') + view.dispatch(w=self.w, columns=columns) + + +class ProgressBarView(EntityView): + """displays a progress bar""" + id = 'progressbar' + title = _('progress bar') + __selectors__ = (accept_selector, interface_selector) + + accepts_interfaces = (IProgress,) + + def cell_call(self, row, col): + self.req.add_css('cubicweb.iprogress.css') + entity = self.entity(row, col) + widget = ProgressBarWidget(entity.done, entity.todo, + entity.revised_cost) + self.w(widget.render()) +