Пример #1
0
 def render(self, ticketset):
   return_div = tag.div(class_=self.cssclass+' projectplanrender' )
   
   # check for missing parameters 
   missingparameter = False
   if self.rows == [] or self.rows == None:
     return_div(tag.div('Missing parameter "rows": use a semicolon-separated list to input the "'+self.rowtype+'".', class_='ppwarning')) 
     missingparameter = True
   if self.rowtype == None or  str(self.rowtype).strip() == '':
     return_div(tag.div('Missing parameter "rowtype": specifies the ticket attribute that should be showed at the rows.', class_='ppwarning')) 
     missingparameter = True
   if self.cols == [] or self.cols == None:
     return_div(tag.div('Missing parameter: use a semicolon-separated list to input the "cols".', class_='ppwarning'))
     missingparameter = True
   if self.coltype == None or  str(self.coltype).strip() == '':
     return_div(tag.div('Missing parameter "coltype": specifies the ticket attribute that should be showed in the columns.', class_='ppwarning')) 
     missingparameter = True
   if missingparameter:
     return return_div
   
   
   #ul = tag.ul()
   #for tid in ticketset.getIDSortedList():
     #ticket = ticketset.getTicket(tid)
     #ul( tag.li(tid, " ",ticket.getfield('component') , " ", ticket.getfield('owner') ))
   #return_div(ul)
   def getstatistictitle( statusdict ):
     mytitle = ''
     mysum = 0
     for status in statusdict:
       mytitle += "%s: %s\n" % (status, str(statusdict[status]) )
       mysum += int(statusdict[status])
     mytitle += "%s: %s" % ('number', mysum)
     return mytitle
   
   def setKV( myStruct, myKey, newValue ):
     '''
       shortcut to set the values correctly
       used to reduce the code needed while using a list as key of a dict
     '''
     myStruct[str(myKey)] = newValue
   
   def tableKeyPrettyPrint( mylist ) :
     '''
       transform a list of keys to a user readable string
       in: ['a','b'] --> out: 'a|b'
     '''
     return '|'.join(mylist)
   
   def tableKeyQueryParameter( parameter, mylist ) :
     '''
       transform a list of keys to a Trac query string parameter  (OR)
       in: x, ['a','b'] --> out: 'x=a&x=b'
     '''
     return '&'.join([ "%s=%s" % (parameter, s) for s in mylist ])
   
   
   chartheight=80
   chartwidth=170
   
   data = {}
   statistics = {}
   
   # init table data 
   for row in self.rows :
     colstatistics = {}
     colkeys = {}
     for col in self.cols :
       # colkeys[col] = []
       setKV( colkeys, col, [] )
       # colstatistics[col] = {}
       setKV( colstatistics, col, {} )
     # data[row] = colkeys
     setKV( data, row, colkeys )
     # statistics[row] = colstatistics
     setKV( statistics, row, colstatistics )
   
   for tid in ticketset.getIDSortedList():
     ticket = ticketset.getTicket(tid)
     ticket_rowtype = ticket.getfield(self.rowtype)
     ticket_coltype =  ticket.getfield(self.coltype)
     
     # determine the data cell where the ticket has to be added, keep in mind that rows and cols are list of lists
     for row in self.rows :
       for col in self.cols :
         if ticket_rowtype in row and ticket_coltype in col :
           data[str(row)][str(col)].append(ticket) # save tickets at precise values of row and col
           self.log_debug('row:%s col:%s append:%s' % (row,col,tid))
     
     # if ticket_rowtype in self.rows and ticket_coltype in self.cols :
   
   # create HTML table
   table = tag.table( class_="data pptableticketperday" , border = "1", style = 'width:auto;')
   
   # create HTML table head
   thead = tag.thead()
   tr = tag.tr()
   tr( tag.th("%s vs %s" % (self.rowtype,self.coltype) ) )
   for colkey in self.cols :
     tr( tag.th(tag.h4(tag.a( tableKeyPrettyPrint(colkey), href=self.macroenv.tracenv.href()+('/query?%s&order=%s' % ( tableKeyQueryParameter(self.coltype, colkey),self.rowtype)) )),title="%s is %s" % (self.coltype, tableKeyPrettyPrint(colkey) ) ) ) # first line with all colkeys
   if self.showsummarypiechart:
     tr( tag.th(tag.h4( "Ticket Overview" ) ) )  
   thead(tr)
   table(thead)
   
   # create HTML table body
   tbody = tag.tbody()
   counter=0
   
   for rowkey in self.rows :
     # switch line color
     if counter % 2 == 1:
       class_ = 'odd'
     else:
       class_ = 'even'
     counter += 1
     tr = tag.tr( class_=class_ ) # new line
     
     td = tag.td() # new cell
     td(tag.h5(tag.a( tableKeyPrettyPrint(rowkey), href=self.macroenv.tracenv.href()+('/query?%s&order=%s' % ( tableKeyQueryParameter( self.rowtype,rowkey),self.coltype)) )),title="%s is %s" % (self.rowtype, tableKeyPrettyPrint(rowkey) ) ) # first cell contains row key
     tr(td)
     for colkey in self.cols :
       td = tag.td()
       for ticket in data[str(rowkey)][str(colkey)] :
         td( tag.span(self.createTicketLink(ticket), class_ = 'ticket_inner' ), " " , mytitle="%s is %s and %s is %s" % (self.rowtype,rowkey,self.coltype,colkey) ) # mytitle might be used later by javascript
         if not statistics[str(rowkey)][str(colkey)].has_key( ticket.getstatus() ) :
           statistics[str(rowkey)][str(colkey)][ticket.getstatus()] = 0
         statistics[str(rowkey)][str(colkey)][ticket.getstatus()] += 1
       tr(td)
     
     # compute statistics
     rowstatistics = {}
     count = 0
     for colkey in statistics[str(rowkey)] :
       for status in statistics[str(rowkey)][str(colkey)] :
         if not rowstatistics.has_key(status) : 
           rowstatistics[status] = 0
         try:
           rowstatistics[status] += statistics[str(rowkey)][str(colkey)][status]
           count += statistics[str(rowkey)][str(colkey)][status]
         except:
           pass
       
     if self.showsummarypiechart:
       tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', rowstatistics, '%s tickets' % (count,), height=chartheight )), class_='ppstatistics' , title=getstatistictitle(rowstatistics)) ) # Summary
     
     tbody(tr)
   table(tbody)
   
   # create HTML table foot
   if self.showsummarypiechart :
     fullstatistics = {}
     tfoot = tag.tfoot()
     tr = tag.tr()
     
     tr( tag.td(tag.h5('Ticket Overview') ) )
     
     # create statistics for col
     fullcount = 0
     for colkey in self.cols :
       colstatistics = {}
       colcount = 0
       for rowkey in self.rows :
         for status in statistics[str(rowkey)][str(colkey)] :
           if not fullstatistics.has_key(status) : 
             fullstatistics[status] = 0
           if not colstatistics.has_key(status) : 
             colstatistics[status] = 0
           try:
             colstatistics[status] += statistics[str(rowkey)][str(colkey)][status]
             colcount += statistics[str(rowkey)][str(colkey)][status]
             fullstatistics[status] += statistics[str(rowkey)][str(colkey)][status]
             fullcount += statistics[str(rowkey)][str(colkey)][status]
           except:
             pass
       tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', colstatistics, '%s tickets' % (colcount,), height=chartheight)), title=getstatistictitle(colstatistics) )) # Col Summary
     tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', fullstatistics, '%s tickets' % (fullcount,), height=chartheight)), class_='ppstatistics', title=getstatistictitle(fullstatistics))) # Full Summary
     tfoot(tr)
     table(tfoot)
   
   return_div(table)
   
   return return_div 
Пример #2
0
          td_div(tag.div( tag.span(self.createTicketLink(ticket), class_ = 'ticket_inner') ) )
          
          if ticket.getfield('status') in countStatus.keys(): # count values
            countStatus[ticket.getfield('status')] += 1
          else:
            countStatus[ticket.getfield('status')] = 1
        
        #tr(tag.td( tag.div( td_div, style = 'border-left:3px solid %s;' % (color) ) ) )
        tr(tag.td( tag.div( td_div ), self.render_statistics(orderedtickets[segment][o]), class_ = '%s %s %s' % (color_class, class_, self.statistics_class)  ) )
      if self.showsummarypiechart:
        tr(tag.td(tag.img(src=self.createGoogleChartFromDict('ColorForStatus', countStatus)))) # Summary
      tbody(tr)
    table(tbody)
    
    countTickets = 0
    tfoot = tag.tfoot()
    tr = tag.tr()
    tr(tag.td(tag.h5(self.rowtype+': '+str(len(self.rows)))))
    for segment in self.segments:
      tr(tag.td(tag.h5(str(counttickets[segment])+' tickets')))
      countTickets += counttickets[segment]
    if self.showsummarypiechart:
      tr(tag.td(tag.h5(str(str(countTickets))+' tickets'))) # Summary
    tfoot(tr)
    table(tfoot)
    
    div(table)
    return div


    def render(self, ticketset):
        return_div = tag.div(class_=self.cssclass + ' projectplanrender')

        # check for missing parameters
        missingparameter = False
        if self.rows == [] or self.rows == None:
            return_div(
                tag.div(
                    'Missing parameter "rows": use a semicolon-separated list to input the "'
                    + self.rowtype + '".',
                    class_='ppwarning'))
            missingparameter = True
        if self.rowtype == None or str(self.rowtype).strip() == '':
            return_div(
                tag.div(
                    'Missing parameter "rowtype": specifies the ticket attribute that should be showed at the rows.',
                    class_='ppwarning'))
            missingparameter = True
        if self.cols == [] or self.cols == None:
            return_div(
                tag.div(
                    'Missing parameter: use a semicolon-separated list to input the "cols".',
                    class_='ppwarning'))
            missingparameter = True
        if self.coltype == None or str(self.coltype).strip() == '':
            return_div(
                tag.div(
                    'Missing parameter "coltype": specifies the ticket attribute that should be showed in the columns.',
                    class_='ppwarning'))
            missingparameter = True
        if missingparameter:
            return return_div

        #ul = tag.ul()
        #for tid in ticketset.getIDSortedList():
        #ticket = ticketset.getTicket(tid)
        #ul( tag.li(tid, " ",ticket.getfield('component') , " ", ticket.getfield('owner') ))
        #return_div(ul)
        def getstatistictitle(statusdict):
            mytitle = ''
            mysum = 0
            for status in statusdict:
                mytitle += "%s: %s\n" % (status, str(statusdict[status]))
                mysum += int(statusdict[status])
            mytitle += "%s: %s" % ('number', mysum)
            return mytitle

        def setKV(myStruct, myKey, newValue):
            '''
        shortcut to set the values correctly
        used to reduce the code needed while using a list as key of a dict
      '''
            myStruct[str(myKey)] = newValue

        def tableKeyPrettyPrint(mylist):
            '''
        transform a list of keys to a user readable string
        in: ['a','b'] --> out: 'a|b'
      '''
            return '|'.join(mylist)

        def tableKeyQueryParameter(parameter, mylist):
            '''
        transform a list of keys to a Trac query string parameter  (OR)
        in: x, ['a','b'] --> out: 'x=a&x=b'
      '''
            return '&'.join(["%s=%s" % (parameter, s) for s in mylist])

        chartheight = 80
        chartwidth = 170

        data = {}
        statistics = {}

        # init table data
        for row in self.rows:
            colstatistics = {}
            colkeys = {}
            for col in self.cols:
                # colkeys[col] = []
                setKV(colkeys, col, [])
                # colstatistics[col] = {}
                setKV(colstatistics, col, {})
            # data[row] = colkeys
            setKV(data, row, colkeys)
            # statistics[row] = colstatistics
            setKV(statistics, row, colstatistics)

        for tid in ticketset.getIDSortedList():
            ticket = ticketset.getTicket(tid)
            ticket_rowtype = ticket.getfield(self.rowtype)
            ticket_coltype = ticket.getfield(self.coltype)

            # determine the data cell where the ticket has to be added, keep in mind that rows and cols are list of lists
            for row in self.rows:
                for col in self.cols:
                    if ticket_rowtype in row and ticket_coltype in col:
                        data[str(row)][str(col)].append(
                            ticket
                        )  # save tickets at precise values of row and col
                        self.log_debug('row:%s col:%s append:%s' %
                                       (row, col, tid))

            # if ticket_rowtype in self.rows and ticket_coltype in self.cols :

        # create HTML table
        table = tag.table(class_="data pptableticketperday",
                          border="1",
                          style='width:auto;')

        # create HTML table head
        thead = tag.thead()
        tr = tag.tr()
        tr(tag.th("%s vs %s" % (self.rowtype, self.coltype)))
        for colkey in self.cols:
            tr(
                tag.th(tag.h4(
                    tag.a(tableKeyPrettyPrint(colkey),
                          href=self.macroenv.tracenv.href() +
                          ('/query?%s&order=%s' % (tableKeyQueryParameter(
                              self.coltype, colkey), self.rowtype)))),
                       title="%s is %s" %
                       (self.coltype, tableKeyPrettyPrint(colkey)))
            )  # first line with all colkeys
        if self.showsummarypiechart:
            tr(tag.th(tag.h4("Ticket Overview")))
        thead(tr)
        table(thead)

        # create HTML table body
        tbody = tag.tbody()
        counter = 0

        for rowkey in self.rows:
            # switch line color
            if counter % 2 == 1:
                class_ = 'odd'
            else:
                class_ = 'even'
            counter += 1
            tr = tag.tr(class_=class_)  # new line

            td = tag.td()  # new cell
            td(tag.h5(
                tag.a(tableKeyPrettyPrint(rowkey),
                      href=self.macroenv.tracenv.href() +
                      ('/query?%s&order=%s' % (tableKeyQueryParameter(
                          self.rowtype, rowkey), self.coltype)))),
               title="%s is %s" %
               (self.rowtype,
                tableKeyPrettyPrint(rowkey)))  # first cell contains row key
            tr(td)
            for colkey in self.cols:
                td = tag.td()
                for ticket in data[str(rowkey)][str(colkey)]:
                    td(tag.span(self.createTicketLink(ticket),
                                class_='ticket_inner'),
                       " ",
                       mytitle="%s is %s and %s is %s" %
                       (self.rowtype, rowkey, self.coltype,
                        colkey))  # mytitle might be used later by javascript
                    if not statistics[str(rowkey)][str(colkey)].has_key(
                            ticket.getstatus()):
                        statistics[str(rowkey)][str(colkey)][
                            ticket.getstatus()] = 0
                    statistics[str(rowkey)][str(colkey)][
                        ticket.getstatus()] += 1
                tr(td)

            # compute statistics
            rowstatistics = {}
            count = 0
            for colkey in statistics[str(rowkey)]:
                for status in statistics[str(rowkey)][str(colkey)]:
                    if not rowstatistics.has_key(status):
                        rowstatistics[status] = 0
                    try:
                        rowstatistics[status] += statistics[str(rowkey)][str(
                            colkey)][status]
                        count += statistics[str(rowkey)][str(colkey)][status]
                    except:
                        pass

            if self.showsummarypiechart:
                tr(
                    tag.td(tag.img(src=self.createGoogleChartFromDict(
                        'ColorForStatus',
                        rowstatistics,
                        '%s tickets' % (count, ),
                        height=chartheight)),
                           class_='ppstatistics',
                           title=getstatistictitle(rowstatistics)))  # Summary

            tbody(tr)
        table(tbody)

        # create HTML table foot
        if self.showsummarypiechart:
            fullstatistics = {}
            tfoot = tag.tfoot()
            tr = tag.tr()

            tr(tag.td(tag.h5('Ticket Overview')))

            # create statistics for col
            fullcount = 0
            for colkey in self.cols:
                colstatistics = {}
                colcount = 0
                for rowkey in self.rows:
                    for status in statistics[str(rowkey)][str(colkey)]:
                        if not fullstatistics.has_key(status):
                            fullstatistics[status] = 0
                        if not colstatistics.has_key(status):
                            colstatistics[status] = 0
                        try:
                            colstatistics[status] += statistics[str(rowkey)][
                                str(colkey)][status]
                            colcount += statistics[str(rowkey)][str(
                                colkey)][status]
                            fullstatistics[status] += statistics[str(rowkey)][
                                str(colkey)][status]
                            fullcount += statistics[str(rowkey)][str(
                                colkey)][status]
                        except:
                            pass
                tr(
                    tag.td(
                        tag.img(src=self.createGoogleChartFromDict(
                            'ColorForStatus',
                            colstatistics,
                            '%s tickets' % (colcount, ),
                            height=chartheight)),
                        title=getstatistictitle(colstatistics)))  # Col Summary
            tr(
                tag.td(
                    tag.img(src=self.createGoogleChartFromDict(
                        'ColorForStatus',
                        fullstatistics,
                        '%s tickets' % (fullcount, ),
                        height=chartheight)),
                    class_='ppstatistics',
                    title=getstatistictitle(fullstatistics)))  # Full Summary
            tfoot(tr)
            table(tfoot)

        return_div(table)

        return return_div
                #tr(tag.td( tag.div( td_div, style = 'border-left:3px solid %s;' % (color) ) ) )
                tr(
                    tag.td(tag.div(td_div),
                           self.render_statistics(orderedtickets[segment][o]),
                           class_='%s %s %s' %
                           (color_class, class_, self.statistics_class)))
            if self.showsummarypiechart:
                tr(
                    tag.td(
                        tag.img(src=self.createGoogleChartFromDict(
                            'ColorForStatus', countStatus))))  # Summary
            tbody(tr)
        table(tbody)

        countTickets = 0
        tfoot = tag.tfoot()
        tr = tag.tr()
        tr(tag.td(tag.h5(self.rowtype + ': ' + str(len(self.rows)))))
        for segment in self.segments:
            tr(tag.td(tag.h5(str(counttickets[segment]) + ' tickets')))
            countTickets += counttickets[segment]
        if self.showsummarypiechart:
            tr(tag.td(tag.h5(str(str(countTickets)) + ' tickets')))  # Summary
        tfoot(tr)
        table(tfoot)

        div(table)
        return div


class TicketTableAvsB(RenderImpl):
Пример #5
0
  def render(self, ticketset):
    # add needed javascript and css files
    self.addJsChartFiles()
    
    if self.firstsegment == None or self.lastsegment == None:
      return self.divWarning('you have to set the time period via the macro parameters. Example: first=2012-02-03, last=2012-02-19 .')
    
    tickets = ticketset.getIDList()
    
    # stop if no tickets available
    if len(tickets) == 0:
      return self.divWarning('No tickets available.')
    
    changes = {}    
    initalvalues = {}
    creationdates = {}
    
    (firstday,lastday) = self.getBoundaries({})
    alldates = self.getAllRelevantDates(firstday, lastday)

    lastdaySecs = lastday
    firstday = self.normalizeToDay(firstday)
    lastday = self.normalizeToDay(lastday)

    (ticketCount, relevantChanges) = self.computeInformationAboutSegment( ticketset, firstday, lastday )


    # count only the tickets that are relevant within the requested time period (firstday,lastday)
    relevantTickets = ticketCount
    closedTickets = {} # change this
    openTickets = {} # change this
    changeDateStrings = relevantChanges.keys()
    changeDateStrings.sort()
    # ticketCount = 70 # DEBUG
    
    for changeDateStr in changeDateStrings: # for each day
      self.macroenv.tracenv.log.debug("changes %4s: %3s (%s)" % (changeDateStr,relevantChanges[changeDateStr], ticketCount))
      self.setKeyIfNotExistsInt( closedTickets, changeDateStr, -1*relevantChanges[changeDateStr] )
      ticketCount = ticketCount + relevantChanges[changeDateStr]  # reduce the number of open tickets
      self.setKeyIfNotExistsInt( openTickets  , changeDateStr, ticketCount)

    # generate HTML 
    holderid = "%s_%s_%d_%d" % (self.getNameOfRenderFrame(),'holder',int(time.time()*1000000),random.randint(1,1024) ) # compute unique element id
    currentday = firstday
    frame = tag.div( class_= 'invisible ppConfBurnDown', id=self.getNameOfRenderFrame()+holderid ) 
    tableData = tag.table( class_="invisible data" , border = "1", style = 'width:auto;')
    trDays = tag.tr()
    trDaysAxis = tag.tr()
    trOpenTickets = tag.tr()
    trClosedTickets = tag.tr()
    trReopenedTickets = tag.tr()
    alldates.sort()
    lastOpenTicket = relevantTickets # fallback: all tickets
    lastClosedTickets = 0
    counter = 0
    todaySecs = self.datetime2seconds( datetime.datetime.today() )
    todayStr = self.getDateString(todaySecs)
    todayid = 0
    maxValue = 0
    if lastdaySecs <= todaySecs: # if today is later then the shown time frame then mark the last column
      todayid = len(alldates)
    for currentday in alldates:
      if currentday == todayStr: # capture the column with the current date
        todayid = counter 
      counter = counter + 1
      trDays(tag.th(currentday.replace("\n"," "))) # text for info box, no line breaks here, because it is limited to 3 lines
      trDaysAxis(tag.th(currentday))
      if openTickets.has_key(currentday) :
        lastOpenTicket = openTickets[currentday]
      trOpenTickets(tag.td(lastOpenTicket))
      if closedTickets.has_key(currentday) :
        lastClosedTickets = closedTickets[currentday]
      else:
        lastClosedTickets = 0
      trClosedTickets(tag.td(lastClosedTickets))
      maxValue = max(len(str(lastClosedTickets)),len(str(lastOpenTicket)),maxValue)
      trReopenedTickets(tag.td('0'))
    
    tableData(tag.thead(trDays))
    tableData(tag.tfoot(trDaysAxis))
    tableData(tag.tbody(trOpenTickets, trClosedTickets, trReopenedTickets ))
    
    
    (label1,label2) = self.getLabel()
    
    # caculate the scale factor for the info box within the chart
    maxGlobal = max( len(str(label1))+maxValue, len(str(label2))+maxValue )
    if self.segment in ['week','twoweek']: # they use long descriptions in the info box
      maxGlobal = max(maxGlobal, 27)
    
    # configuration of renderer
    frame(tag.div( str(relevantTickets), class_ = 'maxTasks' ))
    frame(tag.div( self.width, class_ = 'width' ))
    frame(tag.div( self.height, class_ = 'height' ))
    frame(tag.div( str(maxGlobal), class_ = 'maxlength' ))
    frame(tag.div( label1, class_ = 'label1' ))
    frame(tag.div( label2, class_ = 'label2' ))
    frame(tag.div( str(todayid), class_ = 'today' )) # number of column with the current date
    frame(tag.div( holderid, class_ = 'holder' )) # where to put the chart in
    
    frame(tableData)
    outerframe = tag.div() # div as global container
    #outerframe(outer) # DEBUG
    outerframe(frame)
    outerframe(tag.div( id = holderid ), style="border-width:1px" )
    outerframe(tag.script("$.getScript('%s'); $.getScript('%s'); $.getScript('%s');  " % ('projectplan/js/jquery-burndown/raphael.js', 'projectplan/js/jquery-burndown/raphael_002.js','projectplan/js/jquery-burndown/burndown.js' ) ) )
    return outerframe
Пример #6
0
    def render(self, ticketset):
        # add needed javascript and css files
        self.addJsChartFiles()

        if self.firstsegment == None or self.lastsegment == None:
            return self.divWarning(
                'you have to set the time period via the macro parameters. Example: first=2012-02-03, last=2012-02-19 .'
            )

        tickets = ticketset.getIDList()

        # stop if no tickets available
        if len(tickets) == 0:
            return self.divWarning('No tickets available.')

        changes = {}
        initalvalues = {}
        creationdates = {}

        (firstday, lastday) = self.getBoundaries({})
        alldates = self.getAllRelevantDates(firstday, lastday)

        lastdaySecs = lastday
        firstday = self.normalizeToDay(firstday)
        lastday = self.normalizeToDay(lastday)

        (ticketCount, relevantChanges) = self.computeInformationAboutSegment(
            ticketset, firstday, lastday)

        # count only the tickets that are relevant within the requested time period (firstday,lastday)
        relevantTickets = ticketCount
        closedTickets = {}  # change this
        openTickets = {}  # change this
        changeDateStrings = relevantChanges.keys()
        changeDateStrings.sort()
        # ticketCount = 70 # DEBUG

        for changeDateStr in changeDateStrings:  # for each day
            self.macroenv.tracenv.log.debug(
                "changes %4s: %3s (%s)" %
                (changeDateStr, relevantChanges[changeDateStr], ticketCount))
            self.setKeyIfNotExistsInt(closedTickets, changeDateStr,
                                      -1 * relevantChanges[changeDateStr])
            ticketCount = ticketCount + relevantChanges[
                changeDateStr]  # reduce the number of open tickets
            self.setKeyIfNotExistsInt(openTickets, changeDateStr, ticketCount)

        # generate HTML
        holderid = "%s_%s_%d_%d" % (
            self.getNameOfRenderFrame(), 'holder', int(time.time() * 1000000),
            random.randint(1, 1024))  # compute unique element id
        currentday = firstday
        frame = tag.div(class_='invisible ppConfBurnDown',
                        id=self.getNameOfRenderFrame() + holderid)
        tableData = tag.table(class_="invisible data",
                              border="1",
                              style='width:auto;')
        trDays = tag.tr()
        trDaysAxis = tag.tr()
        trOpenTickets = tag.tr()
        trClosedTickets = tag.tr()
        trReopenedTickets = tag.tr()
        alldates.sort()
        lastOpenTicket = relevantTickets  # fallback: all tickets
        lastClosedTickets = 0
        counter = 0
        todaySecs = self.datetime2seconds(datetime.datetime.today())
        todayStr = self.getDateString(todaySecs)
        todayid = 0
        maxValue = 0
        if lastdaySecs <= todaySecs:  # if today is later then the shown time frame then mark the last column
            todayid = len(alldates)
        for currentday in alldates:
            if currentday == todayStr:  # capture the column with the current date
                todayid = counter
            counter = counter + 1
            trDays(
                tag.th(currentday.replace("\n", " "))
            )  # text for info box, no line breaks here, because it is limited to 3 lines
            trDaysAxis(tag.th(currentday))
            if openTickets.has_key(currentday):
                lastOpenTicket = openTickets[currentday]
            trOpenTickets(tag.td(lastOpenTicket))
            if closedTickets.has_key(currentday):
                lastClosedTickets = closedTickets[currentday]
            else:
                lastClosedTickets = 0
            trClosedTickets(tag.td(lastClosedTickets))
            maxValue = max(len(str(lastClosedTickets)),
                           len(str(lastOpenTicket)), maxValue)
            trReopenedTickets(tag.td('0'))

        tableData(tag.thead(trDays))
        tableData(tag.tfoot(trDaysAxis))
        tableData(tag.tbody(trOpenTickets, trClosedTickets, trReopenedTickets))

        (label1, label2) = self.getLabel()

        # caculate the scale factor for the info box within the chart
        maxGlobal = max(
            len(str(label1)) + maxValue,
            len(str(label2)) + maxValue)
        if self.segment in ['week', 'twoweek'
                            ]:  # they use long descriptions in the info box
            maxGlobal = max(maxGlobal, 27)

        # configuration of renderer
        frame(tag.div(str(relevantTickets), class_='maxTasks'))
        frame(tag.div(self.width, class_='width'))
        frame(tag.div(self.height, class_='height'))
        frame(tag.div(str(maxGlobal), class_='maxlength'))
        frame(tag.div(label1, class_='label1'))
        frame(tag.div(label2, class_='label2'))
        frame(
            tag.div(str(todayid),
                    class_='today'))  # number of column with the current date
        frame(tag.div(holderid, class_='holder'))  # where to put the chart in

        frame(tableData)
        outerframe = tag.div()  # div as global container
        #outerframe(outer) # DEBUG
        outerframe(frame)
        outerframe(tag.div(id=holderid), style="border-width:1px")
        return outerframe