Esempio n. 1
0
 def _render_milestone_list(self, req):
     project_id = req.data['project_id']
     milestones = Milestone.select(self.env, project_id, include_completed=True)
     data = {
         'milestones': milestones,
     }
     return 'mdashboard.html', data, None
Esempio n. 2
0
    def _render_editor(self, req, milestone):
        # Suggest a default due time of 18:00 in the user's timezone
        default_due = datetime.now(req.tz).replace(hour=18,
                                                   minute=0,
                                                   second=0,
                                                   microsecond=0)
        if default_due <= datetime.now(utc):
            default_due += timedelta(days=1)

        data = {
            'milestone': milestone,
            'datetime_hint': get_datetime_format_hint(req.lc_time),
            'default_due': default_due,
            'milestone_groups': [],
        }

        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
            milestones = [
                m for m in Milestone.select(self.env)
                if m.name != milestone.name
                and 'MILESTONE_VIEW' in req.perm(m.resource)
            ]
            data['milestone_groups'] = group_milestones(
                milestones, 'TICKET_ADMIN' in req.perm)
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')

        chrome = Chrome(self.env)
        chrome.add_jquery_ui(req)
        chrome.add_wiki_toolbars(req)
        return 'milestone_edit.html', data, None
Esempio n. 3
0
    def _get_options(self, field_name):
        """Return a list of options for the given [dynvars] field:
        
         [dynvars]
         myfield.options = value1|value2|value3
        
        If no [dynvars] field is found, a select field is searched
        and its options returned.  For the milestone field, completed
        milestones are omitted.  If no select field is found, then an
        empty list is returned."""
        # look for [dynvars] field
        for key, val in self.env.config.options('dynvars'):
            if key == field_name + '.options':
                return val.split('|')

        # handle milestone special - skip completed milestones
        if field_name == 'milestone':
            return [''] + [
                m.name
                for m in Milestone.select(self.env, include_completed=False)
            ]

        # lookup select field
        for field in TicketSystem(self.env).get_ticket_fields():
            if field['name'] == field_name and 'options' in field:
                return field['options']
        return []
Esempio n. 4
0
    def _render_editor(self, req, db, milestone):
        # Suggest a default due time of 18:00 in the user's timezone
        default_due = datetime.now(req.tz).replace(hour=18, minute=0, second=0,
                                                   microsecond=0)
        if default_due <= datetime.now(utc):
            default_due += timedelta(days=1)
        
        data = {
            'milestone': milestone,
            'datetime_hint': get_datetime_format_hint(),
            'default_due': default_due,
            'milestone_groups': [],
        }

        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
            milestones = [m for m in Milestone.select(self.env, db=db)
                          if m.name != milestone.name
                          and 'MILESTONE_VIEW' in req.perm(m.resource)]
            data['milestone_groups'] = group_milestones(milestones,
                'TICKET_ADMIN' in req.perm)
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')

        Chrome(self.env).add_wiki_toolbars(req)
        return 'milestone_edit.html', data, None
Esempio n. 5
0
 def _get_options(self, field_name):
     """Return a list of options for the given [dynvars] field:
     
      [dynvars]
      myfield.options = value1|value2|value3
     
     If no [dynvars] field is found, a select field is searched
     and its options returned.  For the milestone field, completed
     milestones are omitted.  If no select field is found, then an
     empty list is returned."""
     # look for [dynvars] field
     for key,val in self.env.config.options('dynvars'):
         if key == field_name+'.options':
             return val.split('|')
     
     # handle milestone special - skip completed milestones
     if field_name == 'milestone':
         return [''] + [m.name for m in
                 Milestone.select(self.env, include_completed=False)]
     
     # lookup select field
     for field in TicketSystem(self.env).get_ticket_fields():
         if field['name'] == field_name and 'options' in field:
             return field['options']
     return []
Esempio n. 6
0
    def process(self, commit, status, branch):
        self.closestatus = status

        milestones = [
            m.name for m in Milestone.select(self.env) if m.name != 'unknown'
        ]
        if branch.startswith('fixes/'):
            branch = branch[6:]
            milestones = [m for m in milestones if m.startswith(branch)]
        self.milestone = sorted(milestones)[-1]

        msg = commit['message']
        self.env.log.debug("Processing Commit: %s", msg)
        msg = "%s \n Branch:    %s \n Changeset: %s" % (msg, branch,
                                                        commit['id'])
        #        author = commit['author']['name']
        author = 'Github'
        timestamp = datetime.now(utc)

        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), '')
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    if (branch == "master") or branch.startswith("fixes/"):
                        tickets.setdefault(tkt_id,
                                           []).append(getattr(self, funcname))
#                    disable this stuff for now, it causes duplicates on merges
#                    proper implementation of this will require tracking commit hashes
#                    else:
#                        tickets.setdefault(tkt_id, []).append(self._cmdRefs)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change['permanent']:
                        cnum += 1

                ticket.save_changes(author, msg, timestamp, db, cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback
                traceback.print_exc(file=sys.stderr)
Esempio n. 7
0
	def _find_milestones(self):
		"""Return a string list of Milestone names
		
		A smarter approach would return a dictionary of milestones:
		key = name
		value = tuple (name, due, completed, description)
		"""

		return [ "%s" % m.name for m in Milestone.select(self.env) ]
Esempio n. 8
0
    def _find_milestones(self):
        """Return a string list of Milestone names
		
		A smarter approach would return a dictionary of milestones:
		key = name
		value = tuple (name, due, completed, description)
		"""

        return ["%s" % m.name for m in Milestone.select(self.env)]
Esempio n. 9
0
    def process(self, commit, status, branch):
        self.closestatus = status

        milestones = [m.name for m in Milestone.select(self.env) if m.name != "unknown"]
        if branch.startswith("fixes/"):
            branch = branch[6:]
            milestones = [m for m in milestones if m.startswith(branch)]
        self.milestone = sorted(milestones)[-1]

        msg = commit["message"]
        self.env.log.debug("Processing Commit: %s", msg)
        msg = "%s \n Branch:    %s \n Changeset: %s" % (msg, branch, commit["id"])
        #        author = commit['author']['name']
        author = "Github"
        timestamp = datetime.now(utc)

        cmd_groups = command_re.findall(msg)
        self.env.log.debug("Function Handlers: %s" % cmd_groups)

        tickets = {}
        for cmd, tkts in cmd_groups:
            funcname = self.__class__._supported_cmds.get(cmd.lower(), "")
            self.env.log.debug("Function Handler: %s" % funcname)
            if funcname:
                for tkt_id in ticket_re.findall(tkts):
                    if (branch == "master") or branch.startswith("fixes/"):
                        tickets.setdefault(tkt_id, []).append(getattr(self, funcname))
        #                    disable this stuff for now, it causes duplicates on merges
        #                    proper implementation of this will require tracking commit hashes
        #                    else:
        #                        tickets.setdefault(tkt_id, []).append(self._cmdRefs)

        for tkt_id, cmds in tickets.iteritems():
            try:
                db = self.env.get_db_cnx()

                ticket = Ticket(self.env, int(tkt_id), db)
                for cmd in cmds:
                    cmd(ticket)

                # determine sequence number...
                cnum = 0
                tm = TicketModule(self.env)
                for change in tm.grouped_changelog_entries(ticket, db):
                    if change["permanent"]:
                        cnum += 1

                ticket.save_changes(author, msg, timestamp, db, cnum + 1)
                db.commit()

                tn = TicketNotifyEmail(self.env)
                tn.notify(ticket, newticket=0, modtime=timestamp)
            except Exception, e:
                import traceback

                traceback.print_exc(file=sys.stderr)
Esempio n. 10
0
    def _render_confirm(self, req, db, milestone):
        req.perm.assert_permission('MILESTONE_DELETE')

        req.hdf['title'] = 'Jalon %s' % milestone.name
        req.hdf['milestone'] = milestone_to_hdf(self.env, db, req, milestone)
        req.hdf['milestone.mode'] = 'delete'

        for idx,other in enumerate(Milestone.select(self.env, False, db)):
            if other.name == milestone.name:
                continue
            req.hdf['milestones.%d' % idx] = other.name
Esempio n. 11
0
    def _render_confirm(self, req, db, milestone):
        req.perm.assert_permission('MILESTONE_DELETE')

        req.hdf['title'] = 'Milestone %s' % milestone.name
        req.hdf['milestone'] = milestone_to_hdf(self.env, db, req, milestone)
        req.hdf['milestone.mode'] = 'delete'

        for idx, other in enumerate(Milestone.select(self.env, False, db)):
            if other.name == milestone.name:
                continue
            req.hdf['milestones.%d' % idx] = other.name
Esempio n. 12
0
 def _get_milestone(self, req):
     """Extract the milestone from the referer url.  If not found then
     return the current milestone."""
     path = req.environ.get('HTTP_REFERER', '')
     milestone_re = re.compile(r"/milestone/(?P<milestone>[^?]+)")
     match = milestone_re.search(path)
     if match:
         name = urllib.unquote(match.groupdict()['milestone'])
         for m in Milestone.select(self.env, include_completed=True):
             if m.name == name:
                 return m
         else:
             raise Exception("Milestone %s not found" % name)
     else:
         # milestone not found in url, so assume current milestone
         for m in Milestone.select(self.env, include_completed=False):
             return m
         else:
             raise Exception("No provided or current milestone")
     return None
Esempio n. 13
0
 def _get_milestone(self, req):
     """Extract the milestone from the referer url.  If not found then
     return the current milestone."""
     path = req.environ.get('HTTP_REFERER','')
     milestone_re = re.compile(r"/milestone/(?P<milestone>[^?]+)")
     match = milestone_re.search(path)
     if match:
         name = urllib.unquote(match.groupdict()['milestone'])
         for m in Milestone.select(self.env, include_completed=True):
             if m.name == name:
                 return m
         else:
             raise Exception("Milestone %s not found" % name)
     else:
         # milestone not found in url, so assume current milestone
         for m in Milestone.select(self.env, include_completed=False):
             return m
         else:
             raise Exception("No provided or current milestone")
     return None
Esempio n. 14
0
    def _render_confirm(self, req, milestone):
        req.perm(milestone.resource).require('MILESTONE_DELETE')

        milestones = [m for m in Milestone.select(self.env)
                      if m.name != milestone.name
                      and 'MILESTONE_VIEW' in req.perm(m.resource)]
        data = {
            'milestone': milestone,
            'milestone_groups': group_milestones(milestones,
                'TICKET_ADMIN' in req.perm)
        }
        return 'milestone_delete.html', data, None
Esempio n. 15
0
    def _render_confirm(self, req, db, milestone):
        req.perm(milestone.resource).require('MILESTONE_DELETE')

        milestones = [m for m in Milestone.select(self.env, db=db)
                      if m.name != milestone.name
                      and 'MILESTONE_VIEW' in req.perm(m.resource)]
        data = {
            'milestone': milestone,
            'milestone_groups': group_milestones(milestones,
                'TICKET_ADMIN' in req.perm)
        }
        return 'milestone_delete.html', data, None
Esempio n. 16
0
def execute(hdf, txt, env):
    out = StringIO()
    out.write('<ul>\n')
    for milestone in Milestone.select(env, include_completed=False):
        if milestone.due > 0:
            date = format_date(milestone.due)
        else:
            date = Markup('<i>(later)</i>')
        out.write(Markup('<li>%s - <a href="%s">%s</a></li>\n',
                         date, env.href.milestone(milestone.name),
                         milestone.name))
    out.write('</ul>\n')
    return out.getvalue()
Esempio n. 17
0
def execute(hdf, txt, env):
    out = StringIO()
    out.write('<ul>\n')
    for milestone in Milestone.select(env, include_completed=False):
        if milestone.due > 0:
            date = format_date(milestone.due)
        else:
            date = Markup('<i>(later)</i>')
        out.write(
            Markup('<li>%s - <a href="%s">%s</a></li>\n', date,
                   env.href.milestone(milestone.name), milestone.name))
    out.write('</ul>\n')
    return out.getvalue()
Esempio n. 18
0
    def process_request(self, req):
        req.perm.require('MILESTONE_VIEW')

        show = req.args.getlist('show')
        if 'all' in show:
            show = ['completed']

        db = self.env.get_db_cnx()
        milestones = Milestone.select(self.env, 'completed' in show, db)
        if 'noduedate' in show:
            milestones = [
                m for m in milestones if m.due is not None or m.completed
            ]
        milestones = [
            m for m in milestones if 'MILESTONE_VIEW' in req.perm(m.resource)
        ]

        stats = []
        queries = []

        for milestone in milestones:
            tickets = get_tickets_for_milestone(self.env, db, milestone.name,
                                                'owner')
            tickets = apply_ticket_permissions(self.env, req, tickets)
            stat = get_ticket_stats(self.stats_provider, tickets)
            stats.append(
                milestone_stats_data(self.env, req, stat,
                                     '^' + milestone.name))
            #milestone['tickets'] = tickets # for the iCalendar view

        if req.args.get('format') == 'ics':
            self.render_ics(req, db, milestones)
            return

        # FIXME should use the 'webcal:' scheme, probably
        username = None
        if req.authname and req.authname != 'anonymous':
            username = req.authname
        icshref = req.href.roadmap(show=show, user=username, format='ics')
        add_link(req, 'alternate', icshref, _('iCalendar'), 'text/calendar',
                 'ics')

        data = {
            'milestones': milestones,
            'milestone_stats': stats,
            'queries': queries,
            'show': show,
        }
        add_stylesheet(req, 'common/css/roadmap.css')
        return 'roadmap.html', data, None
Esempio n. 19
0
    def expand_macro(self, formatter, name, content):

        arg, kwarg = parse_args(content)

        includepattern = kwarg.get('include', '')
        #excludepattern = kwarg.get('exclude', '')
        length = int(kwarg.get('max', -1))
        ignorenoduedate = kwarg.get('ignore') == 'noduedate' or None

        if length == -1:
            length = None

        out = StringIO()

        include = re.compile(includepattern)
        #exclude = re.compile(excludepattern)

        milestones = []

        for milestone in Milestone.select(self.env, include_completed=False):
            if include.match(
                    milestone.name):  # and not exclude.match(milestone.name):
                milestones.append(milestone)

        out.write('<ul>\n')
        for milestone in milestones[0:length]:

            if milestone.due:
                #TODO: add one day to tdelta
                tdelta = (to_timestamp(milestone.due) -
                          to_timestamp(datetime.now(formatter.req.tz)))
                if tdelta > 0:
                    date = format_date(milestone.due, '%Y-%m-%d',
                                       formatter.req.tz)
                else:
                    date = None
            elif not ignorenoduedate:
                date = Markup('<i>(Unspecified)</i>')
            else:
                date = None

            if date:
                out.write('<li>%s - <a href="%s">%s</a></li>\n' %
                          (date, self.env.href.milestone(
                              milestone.name), milestone.name))

        out.write('</ul>\n')
        return Markup(out.getvalue())
Esempio n. 20
0
    def process_request(self, req):
        req.perm.require('MILESTONE_VIEW')

        show = req.args.getlist('show')
        if 'all' in show:
            show = ['completed']

        db = self.env.get_db_cnx()
        milestones = Milestone.select(self.env, 'completed' in show, db)
        if 'noduedate' in show:
            milestones = [m for m in milestones
                          if m.due is not None or m.completed]
        milestones = [m for m in milestones
                      if 'MILESTONE_VIEW' in req.perm(m.resource)]

        stats = []
        queries = []

        for milestone in milestones:
            tickets = get_tickets_for_milestone(self.env, db, milestone.name,
                                                'owner')
            tickets = apply_ticket_permissions(self.env, req, tickets)
            stat = get_ticket_stats(self.stats_provider, tickets)
            stats.append(milestone_stats_data(self.env, req, stat,
                                              milestone.name))
            #milestone['tickets'] = tickets # for the iCalendar view

        if req.args.get('format') == 'ics':
            self.render_ics(req, db, milestones)
            return

        # FIXME should use the 'webcal:' scheme, probably
        username = None
        if req.authname and req.authname != 'anonymous':
            username = req.authname
        icshref = req.href.roadmap(show=show, user=username, format='ics')
        add_link(req, 'alternate', icshref, _('iCalendar'), 'text/calendar',
                 'ics')

        data = {
            'milestones': milestones,
            'milestone_stats': stats,
            'queries': queries,
            'show': show,
        }
        add_stylesheet(req, 'common/css/roadmap.css')
        return 'roadmap.html', data, None
Esempio n. 21
0
    def expand_macro(self, formatter, name, content):
        
        arg,kwarg = parse_args(content)
        
        includepattern = kwarg.get('include', '')
        #excludepattern = kwarg.get('exclude', '')
        length = int(kwarg.get('max', -1))
        ignorenoduedate = kwarg.get('ignore') == 'noduedate' or None
        
        if length==-1:
            length = None
        
        out = StringIO()
        
        include = re.compile(includepattern)
        #exclude = re.compile(excludepattern)

        milestones = []
        
        for milestone in Milestone.select(self.env, include_completed=False):
            if include.match(milestone.name): # and not exclude.match(milestone.name):
                milestones.append(milestone)
                
        out.write('<ul>\n')
        for milestone in milestones[0:length]:

            if milestone.due:
                #TODO: add one day to tdelta
                tdelta = (to_timestamp(milestone.due) -
                          to_timestamp(datetime.now(formatter.req.tz)))
                if tdelta > 0:
                    date = format_date(milestone.due, '%Y-%m-%d',
                                       formatter.req.tz)
                else:
                    date = None
            elif not ignorenoduedate:
                date = Markup('<i>(Unspecified)</i>')
            else:
                date = None
                
            if date:        
                out.write('<li>%s - <a href="%s">%s</a></li>\n' % 
                          (date, self.env.href.milestone(milestone.name),
                           milestone.name))
            
        out.write('</ul>\n')
        return Markup(out.getvalue())
Esempio n. 22
0
    def process_admin_request(self, req, cat, page, path_info):
        req.perm.assert_permission('RT_ADMIN')

        update = ""
        for key in req.args.keys():
            if key.startswith("update_"):
                update = key[len("update_"):]
                break

        if update:
            # update now
            base_path = self.env.config.get('rtadmin', 'base_path')
            run_burndown = "python " + os.path.join(
                base_path, "run_burndown.py %s" % update.encode("utf-8"))
            os.system(run_burndown)

        elif req.args.get('save') and req.args.get('sel'):

            # empty table first
            RT_Template.deleteAll(self.env)

            # insert selected milestone into table
            sel = req.args.get('sel')
            sel = isinstance(sel, list) and sel or [sel]
            db = self.env.get_db_cnx()
            for milestone in sel:
                RT_Template.insert(self.env, milestone)
            db.commit()
            req.redirect(self.env.href.admin(cat, page))

        # get all enabled milestones
        enabledMilestones = RT_Template.getMilestones(self.env)

        ms = Milestone.select(self.env)
        ms.sort(cmp=lambda x, y: cmp(x.name, y.name))

        req.hdf['milestones'] = [{
            'name': m.name,
            'href': self.env.href.admin(cat, page, m.name),
            'enabled': m.name in enabledMilestones,
            'update': stripMilestoneName(m.name),
        } for m in ms]

        return 'admin_relaticket.cs', None
Esempio n. 23
0
   def process_request(self, req, chrome, projects):
        milestones = []
        stats = []
        for project in projects:
            env = project["env"]
            for m in Milestone.select(env, False, env.get_db_cnx()):
                req.href = env.href
                milestone = milestone_to_hdf(env, env.get_db_cnx(), req, m)
                milestone['project'] = project
                milestones.append(milestone)

        milestones.sort(milestone_cmp)

        idx = 0
        for m in milestones:
            project = m['project']
            env = project['env']
            milestone_name = unescape(m['name']) # Kludge
            prefix = 'roadmap.milestones.%d.' % idx
            tickets = get_tickets_for_milestone(env, env.get_db_cnx(), milestone_name,
                                                'owner')
            stat = calc_ticket_stats(tickets)
            stats.append({'stats': stat})
            m['queries'] = {}
            for k, v in get_query_links(env, milestone_name).items():
                m['queries'][k] = v
            m['tickets'] = tickets # for the iCalendar view
            idx += 1

            # make milestone names unique
            m["name"] = project["name"] + " " + m["name"]

        data = {
            'milestones': milestones,
            'milestone_stats': stats
        }

        data["chrome.nav.mainnav.roadmap.active"] = 1
        data['title'] = _('Roadmap')
        template_dir = os.path.dirname(__file__) + '/templates/'
        chrome.populate_data(req, data)
        output = chrome.render_template(req, template_dir + "roadmap.html", data)
        req.session.save()
        req.send(output, 'text/html')
Esempio n. 24
0
    def _render_editor(self, req, db, milestone):
        if milestone.exists:
            req.perm.assert_permission('MILESTONE_MODIFY')
            req.hdf['title'] = u'Jalon %s' % milestone.name
            req.hdf['milestone.mode'] = 'edit'
            req.hdf['milestones'] = [m.name for m in
                                     Milestone.select(self.env)
                                     if m.name != milestone.name]
        else:
            req.perm.assert_permission('MILESTONE_CREATE')
            req.hdf['title'] = u'Nouveau jalon'
            req.hdf['milestone.mode'] = 'new'

        from trac.util.datefmt import get_date_format_hint, \
                                       get_datetime_format_hint
        req.hdf['milestone'] = milestone_to_hdf(self.env, db, req, milestone)
        req.hdf['milestone.date_hint'] = get_date_format_hint()
        req.hdf['milestone.datetime_hint'] = get_datetime_format_hint()
        req.hdf['milestone.datetime_now'] = format_datetime()
Esempio n. 25
0
    def _render_editor(self, req, db, milestone):
        data = {
            'milestone': milestone,
            'date_hint': get_date_format_hint(),
            'datetime_hint': get_datetime_format_hint(),
            'milestone_groups': [],
        }

        if milestone.exists:
            req.perm(milestone.resource).require('MILESTONE_MODIFY')
            milestones = [m for m in Milestone.select(self.env, db=db)
                          if m.name != milestone.name
                          and 'MILESTONE_VIEW' in req.perm(m.resource)]
            data['milestone_groups'] = group_milestones(milestones,
                'TICKET_ADMIN' in req.perm)
        else:
            req.perm(milestone.resource).require('MILESTONE_CREATE')

        return 'milestone_edit.html', data, None
Esempio n. 26
0
    def process_admin_request(self, req, cat, page, path_info):
        req.perm.assert_permission('RT_ADMIN')

        update = ""
        for key in req.args.keys():
            if key.startswith("update_"):
                update = key[len("update_"):]
                break

        if update:
            # update now
            base_path = self.env.config.get('rtadmin', 'base_path')
            run_burndown = "python " + os.path.join(base_path, "run_burndown.py %s" % update.encode("utf-8"))
            os.system(run_burndown)

        elif req.args.get('save') and req.args.get('sel'):

            # empty table first
            RT_Template.deleteAll(self.env)
            
            # insert selected milestone into table
            sel = req.args.get('sel')
            sel = isinstance(sel, list) and sel or [sel]
            db = self.env.get_db_cnx()
            for milestone in sel:
                RT_Template.insert(self.env, milestone)
            db.commit()
            req.redirect(self.env.href.admin(cat, page))

        # get all enabled milestones
        enabledMilestones = RT_Template.getMilestones(self.env)

        ms = Milestone.select(self.env)
        ms.sort(cmp=lambda x,y: cmp(x.name, y.name))

        req.hdf['milestones'] = [{'name': m.name,
              'href': self.env.href.admin(cat, page, m.name),
              'enabled': m.name in enabledMilestones,
              'update': stripMilestoneName(m.name),
             } for m in ms]

        return 'admin_relaticket.cs', None
Esempio n. 27
0
    def _render_editor(self, req, db, milestone):
        if milestone.exists:
            req.perm.assert_permission('MILESTONE_MODIFY')
            req.hdf['title'] = 'Milestone %s' % milestone.name
            req.hdf['milestone.mode'] = 'edit'
            req.hdf['milestones'] = [
                m.name for m in Milestone.select(self.env)
                if m.name != milestone.name
            ]
        else:
            req.perm.assert_permission('MILESTONE_CREATE')
            req.hdf['title'] = 'New Milestone'
            req.hdf['milestone.mode'] = 'new'

        from trac.util.datefmt import get_date_format_hint, \
                                       get_datetime_format_hint
        req.hdf['milestone'] = milestone_to_hdf(self.env, db, req, milestone)
        req.hdf['milestone.date_hint'] = get_date_format_hint()
        req.hdf['milestone.datetime_hint'] = get_datetime_format_hint()
        req.hdf['milestone.datetime_now'] = format_datetime()
Esempio n. 28
0
    def process_request(self, req):
        req.perm.assert_permission('ROADMAP_VIEW')
        req.hdf['title'] = 'Roadmap'

        showall = req.args.get('show') == 'all'
        req.hdf['roadmap.showall'] = showall

        db = self.env.get_db_cnx()
        milestones = [
            milestone_to_hdf(self.env, db, req, m)
            for m in Milestone.select(self.env, showall, db)
        ]
        req.hdf['roadmap.milestones'] = milestones

        for idx, milestone in enumerate(milestones):
            milestone_name = unescape(milestone['name'])  # Kludge
            prefix = 'roadmap.milestones.%d.' % idx
            tickets = get_tickets_for_milestone(self.env, db, milestone_name,
                                                'owner')
            req.hdf[prefix + 'stats'] = calc_ticket_stats(tickets)
            for k, v in get_query_links(req, milestone_name).items():
                req.hdf[prefix + 'queries.' + k] = v
            milestone['tickets'] = tickets  # for the iCalendar view

        if req.args.get('format') == 'ics':
            self.render_ics(req, db, milestones)
            return

        add_stylesheet(req, 'common/css/roadmap.css')

        # FIXME should use the 'webcal:' scheme, probably
        username = None
        if req.authname and req.authname != 'anonymous':
            username = req.authname
        icshref = req.href.roadmap(show=req.args.get('show'),
                                   user=username,
                                   format='ics')
        add_link(req, 'alternate', icshref, 'iCalendar', 'text/calendar',
                 'ics')

        return 'roadmap.cs', None
Esempio n. 29
0
    def _get_start_date(self, milestone):
        """Returns the start date for the given milestone based on the
        prior milestone as follows - this milestone's start date =
        
         * the day after the prior milestone's completed date (if completed)
         * else the day after the prior milestone's due date (if due)
         * else today
        """
        prior = None
        for m in Milestone.select(self.env, include_completed=True):
            if m.name == milestone.name:
                break
            prior = m
        else:
            raise Exception("Milestone %s not found" % milestone.name)

        if prior:
            if prior.completed:
                return self._get_day(prior.completed, 'next')
            if prior.due:
                return self._get_day(prior.due, 'next')
        return self._get_day(datetime.utcnow(), 'end')
Esempio n. 30
0
 def _get_start_date(self, milestone):
     """Returns the start date for the given milestone based on the
     prior milestone as follows - this milestone's start date =
     
      * the day after the prior milestone's completed date (if completed)
      * else the day after the prior milestone's due date (if due)
      * else today
     """
     prior = None
     for m in Milestone.select(self.env, include_completed=True):
         if m.name == milestone.name:
             break
         prior = m
     else:
         raise Exception("Milestone %s not found" % milestone.name)
     
     if prior:
         if prior.completed:
             return self._get_day(prior.completed, 'next')
         if prior.due:
             return self._get_day(prior.due, 'next')
     return self._get_day(datetime.utcnow(), 'end')
Esempio n. 31
0
    def process_request(self, req):
        req.perm.assert_permission('ROADMAP_VIEW')
        req.hdf['title'] = u'Feuille de route'

        showall = req.args.get('show') == 'all'
        req.hdf['roadmap.showall'] = showall

        db = self.env.get_db_cnx()
        milestones = [milestone_to_hdf(self.env, db, req, m)
                      for m in Milestone.select(self.env, showall, db)]
        req.hdf['roadmap.milestones'] = milestones        

        for idx, milestone in enumerate(milestones):
            milestone_name = unescape(milestone['name']) # Kludge
            prefix = 'roadmap.milestones.%d.' % idx
            tickets = get_tickets_for_milestone(self.env, db, milestone_name,
                                                'owner')
            req.hdf[prefix + 'stats'] = calc_ticket_stats(tickets)
            for k, v in get_query_links(req, milestone_name).items():
                req.hdf[prefix + 'queries.' + k] = v
            milestone['tickets'] = tickets # for the iCalendar view

        if req.args.get('format') == 'ics':
            self.render_ics(req, db, milestones)
            return

        add_stylesheet(req, 'common/css/roadmap.css')

        # FIXME should use the 'webcal:' scheme, probably
        username = None
        if req.authname and req.authname != 'anonymous':
            username = req.authname
        icshref = req.href.roadmap(show=req.args.get('show'),
                                        user=username, format='ics')
        add_link(req, 'alternate', icshref, 'iCalendar', 'text/calendar', 'ics')

        return 'roadmap.cs', None
Esempio n. 32
0
    def _render_view(self, req, milestone):
        milestone_groups = []
        available_groups = []
        component_group_available = False
        ticket_fields = TicketSystem(self.env).get_ticket_fields()

        # collect fields that can be used for grouping
        for field in ticket_fields:
            if field['type'] == 'select' and field['name'] != 'milestone' \
                    or field['name'] in ('owner', 'reporter'):
                available_groups.append({
                    'name': field['name'],
                    'label': field['label']
                })
                if field['name'] == 'component':
                    component_group_available = True

        # determine the field currently used for grouping
        by = None
        if component_group_available:
            by = 'component'
        elif available_groups:
            by = available_groups[0]['name']
        by = req.args.get('by', by)

        tickets = get_tickets_for_milestone(self.env,
                                            milestone=milestone.name,
                                            field=by)
        tickets = apply_ticket_permissions(self.env, req, tickets)
        stat = get_ticket_stats(self.stats_provider, tickets)

        context = web_context(req, milestone.resource)
        data = {
            'context': context,
            'milestone': milestone,
            'attachments': AttachmentModule(self.env).attachment_data(context),
            'available_groups': available_groups,
            'grouped_by': by,
            'groups': milestone_groups
        }
        data.update(milestone_stats_data(self.env, req, stat, milestone.name))

        if by:

            def per_group_stats_data(gstat, group_name):
                return milestone_stats_data(self.env, req, gstat,
                                            milestone.name, by, group_name)

            milestone_groups.extend(
                grouped_stats_data(self.env, self.stats_provider, tickets, by,
                                   per_group_stats_data))

        add_stylesheet(req, 'common/css/roadmap.css')
        add_script(req, 'common/js/folding.js')

        def add_milestone_link(rel, milestone):
            href = req.href.milestone(milestone.name, by=req.args.get('by'))
            add_link(req, rel, href,
                     _('Milestone "%(name)s"', name=milestone.name))

        milestones = [
            m for m in Milestone.select(self.env)
            if 'MILESTONE_VIEW' in req.perm(m.resource)
        ]
        idx = [i for i, m in enumerate(milestones) if m.name == milestone.name]
        if idx:
            idx = idx[0]
            if idx > 0:
                add_milestone_link('first', milestones[0])
                add_milestone_link('prev', milestones[idx - 1])
            if idx < len(milestones) - 1:
                add_milestone_link('next', milestones[idx + 1])
                add_milestone_link('last', milestones[-1])
        prevnext_nav(req, _('Previous Milestone'), _('Next Milestone'),
                     _('Back to Roadmap'))

        return 'milestone_view.html', data, None
Esempio n. 33
0
 def get_entries_for_index(self):
     for milestone in Milestone.select(self.env, include_completed=True):
         yield self.build_doc(milestone)
Esempio n. 34
0
    def process_admin_request(self, req, cat, page, milestone):
        req.perm.assert_permission('MMV_ADMIN')


        if req.args.get('save'):
            # save 

            # empty table first
            MMV_List.deleteAll(self.env)
            
            # insert selected milestone into table
            db = self.env.get_db_cnx()

            selReq = req.args.get('sel')
            milestoneReq = req.args.get('milestone')
            startdateReq = req.args.get('startdate')
            enddateReq = req.args.get('enddate')

            selList = isinstance(selReq, list) and selReq or [selReq]
            milestoneList = isinstance(milestoneReq, list) and milestoneReq or [milestoneReq]
            startdateList = isinstance(startdateReq, list) and startdateReq or [startdateReq]
            enddateList = isinstance(enddateReq, list) and enddateReq or [enddateReq]

            for milestone, startdate, enddate in zip(milestoneList, startdateList, enddateList):
                startdate = getDateFromStr(startdate)
                enddate = getDateFromStr(enddate)
                if milestone in selList:
                    enabled = True
                else:
                    enabled = False

                MMV_List.insert(self.env, milestone, startdate, enddate, enabled)
            db.commit()
            req.redirect(self.env.href.admin(cat, page))

        elif req.args.get('repair'):
            # repair 

            # empty table first
            MMV_List.deleteAllHistory(self.env)
            
            req.redirect(self.env.href.admin(cat, page))

        else:
            # display

            # get all enabled milestones
            enabledMilestones = MMV_List.getEnabledMilestones(self.env)

            ms = Milestone.select(self.env)
            ms.sort(cmp=lambda x,y: cmp(x.name, y.name))

            req.hdf['date_hint'] = "Format: YYYY/MM/DD"

            req.hdf['milestones'] = [{'name': m.name,
                  'href': self.env.href.admin(cat, "milestones", m.name),
                  'enabled': m.name in enabledMilestones,
                  'startdate':  formatDateFull(MMV_List.getStartdateFromDb(self.env, m.name)), 
                  'enddate': formatDateFull(MMV_List.getEnddateFromDb(self.env, m.name)),
                 } for m in ms]

            return 'mmv_admin.cs', None
Esempio n. 35
0
 def _get_milestones(self):
     #db = self.env.get_db_cnx()
     milestones = Milestone.select(self.env)
     return milestones
Esempio n. 36
0
 def get_entries_for_index(self):
     for milestone in Milestone.select(self.env, include_completed=True):
         yield self.build_doc(milestone)
Esempio n. 37
0
    def process_request(self, req):
        if req.path_info == '/flashgantt/chartxml':
            req.perm.require('MILESTONE_VIEW')
        
            showall = req.args.get('show') == 'all'

            # Get the current date and time
            cur_dt = datetime.date.today()

            # Get the quarter I am in.
            cur_quarter = self._get_quarter(cur_dt.month)
            prev_quarter = self._get_prev_quarter(cur_quarter)
            next_quarter = self._get_next_quarter(cur_quarter)

            (cq_sd, cq_ed) = self._get_quarter_start_end_dates(cur_dt.year, cur_quarter)
            (pq_sd, pq_ed) = self._get_prev_quarters_start_end_dates(cur_dt.year, cur_quarter)
            (nq_sd, nq_ed) = self._get_next_quarters_start_end_dates(cur_dt.year, cur_quarter)
            min_date = pq_sd.strftime('%d/%m/%Y')
            max_date = nq_ed.strftime('%d/%m/%Y')

            quarters = []
            quarters.append({'name': 'Q' + str(prev_quarter) + ' ' + str(pq_sd.year), 'start_date': pq_sd.strftime('%d/%m/%Y'), 'end_date': pq_ed.strftime('%d/%m/%Y')})
            quarters.append({'name': 'Q' + str(cur_quarter) + ' ' + str(cq_sd.year), 'start_date': cq_sd.strftime('%d/%m/%Y'), 'end_date': cq_ed.strftime('%d/%m/%Y')})
            quarters.append({'name': 'Q' + str(next_quarter) + ' ' + str(nq_sd.year), 'start_date': nq_sd.strftime('%d/%m/%Y'), 'end_date': nq_ed.strftime('%d/%m/%Y')})
            
            months = []
            for x in range(pq_sd.month, (pq_ed.month + 1)):
                (cm_sd, cm_ed) = self._get_month_start_end_dates(pq_sd.year, x)
                months.append({'name': self._get_month_name(x), 'start_date': cm_sd.strftime('%d/%m/%Y'), 'end_date': cm_ed.strftime('%d/%m/%Y')})
            for x in range(cq_sd.month, (cq_ed.month + 1)):
                (cm_sd, cm_ed) = self._get_month_start_end_dates(cq_sd.year, x)
                months.append({'name': self._get_month_name(x), 'start_date': cm_sd.strftime('%d/%m/%Y'), 'end_date': cm_ed.strftime('%d/%m/%Y')})
            for x in range(nq_sd.month, (nq_ed.month + 1)):
                (cm_sd, cm_ed) = self._get_month_start_end_dates(nq_sd.year, x)
                months.append({'name': self._get_month_name(x), 'start_date': cm_sd.strftime('%d/%m/%Y'), 'end_date': cm_ed.strftime('%d/%m/%Y')})

            milestones = []
            db = self.env.get_db_cnx()
            ms = [m for m in Milestone.select(self.env, showall, db)
                  if 'MILESTONE_VIEW' in req.perm(m.resource)]
            cnt = 0
            for m in ms:
                cnt = cnt + 1
                comp_stat = 0
                if (m.is_completed):
                    comp_stat = 1
                milestones.append({'name': m.name, 'id': str(cnt),
                'start_date': pq_sd.strftime('%d/%m/%Y'),
                'due_date': format_date(m.due, format='%d/%m/%Y'),
                'completed_date': format_date(m.completed, format='%d/%m/%Y'),
                'completed': comp_stat})
            data = {'milestones': milestones, 'showall': showall, 'visible_months': months, 'quarters': quarters}
                
            # This tuple is for Genshi (template_name, data, content_type)
            # Without data the trac layout will not appear.
            return ('chart.xml', data, 'text/xml')
        else:
            
            req.perm.require('MILESTONE_VIEW')
        
            showall = req.args.get('show') == 'all'

            db = self.env.get_db_cnx()
            milestones = [m for m in Milestone.select(self.env, showall, db)
                          if 'MILESTONE_VIEW' in req.perm(m.resource)]

            chart_height = 150 + (len(milestones) * 29)
            if (showall):
                xmlcharturl = req.href.flashgantt('/chartxml?show=all')
            else:
                xmlcharturl = req.href.flashgantt('/chartxml')

            data = {'milestones': milestones, 'showall': showall,
            'xmlcharturl': xmlcharturl, 'chart_height': chart_height}
        
            #add_stylesheet(req, 'fg/css/flashgantt.css')
        
            # This tuple is for Genshi (template_name, data, content_type)
            # Without data the trac layout will not appear.
            return ('flashgantt.html', data, None)
Esempio n. 38
0
   def process_request(self, req):
       req.perm.require('TSTATS_VIEW')
       req_content = req.args.get('content')
       milestone = None
      
       if not None in [req.args.get('end_date'), req.args.get('start_date'), req.args.get('resolution')]:
         # form submit
         grab_at_date = req.args.get('end_date')
         grab_from_date = req.args.get('start_date')
         grab_resolution = req.args.get('resolution')
         grab_milestone = req.args.get('milestone')
         if grab_milestone == "__all":
            milestone = None
         else:
            milestone = grab_milestone

         # validate inputs
         if None in [grab_at_date, grab_from_date]:
            raise TracError('Please specify a valid range.')

         if None in [grab_resolution]:
            raise TracError('Please specify the graph interval.')
         
         if 0 in [len(grab_at_date), len(grab_from_date), len(grab_resolution)]:
            raise TracError('Please ensure that all fields have been filled in.')

         if not grab_resolution.isdigit():
            raise TracError('The graph interval field must be an integer, days.')

         at_date = parse_date(grab_at_date)
         at_date = datetime.combine(at_date, time(11,59,59,0,utc)) # Add tzinfo

         from_date = parse_date(grab_from_date)
         from_date = datetime.combine(from_date, time(0,0,0,0,utc)) # Add tzinfo

         graph_res = int(grab_resolution)

       else:
         # default data
         todays_date = date.today()
         at_date = datetime.combine(todays_date,time(11,59,59,0,utc))
         from_date = at_date - timedelta(self.default_days_back)
         graph_res = self.default_interval
   
         at_date_str = format_date(at_date)
         from_date_str=  format_date(from_date)
         
       count = []

       # Calculate 0th point
       last_date = from_date - timedelta(graph_res)
       last_num_open = self._get_num_open_tix(last_date, milestone, req)

       # Calculate remaining points
       for cur_date in daterange(from_date, at_date, graph_res):
          num_open = self._get_num_open_tix(cur_date, milestone, req)
          num_closed = self._get_num_closed_tix(last_date, cur_date, milestone, req)
          datestr = format_date(cur_date) 
          if graph_res != 1:
            datestr = "%s thru %s" % (format_date(last_date), datestr) 
          count.append( {'date'  : datestr,
                   'new'   : num_open - last_num_open + num_closed,
                   'closed': num_closed,
                   'open'  : num_open })
          last_num_open = num_open
          last_date = cur_date

       # if chartdata is requested, raw text is returned rather than data object
       # for templating
       if (not req_content == None) and (req_content == "chartdata"):
          jsdstr = '{"chartdata": [\n'
          for x in count:
             jsdstr += '{"date": "%s",' % x['date']
             jsdstr += ' "new_tickets": %s,' % x['new']
             jsdstr += ' "closed": %s,' % x['closed']
             jsdstr += ' "open": %s},\n' % x['open']
          jsdstr = jsdstr[:-2] +'\n]}'
          req.send(jsdstr.encode('utf-8'))
          return 
       else:
          db = self.env.get_db_cnx()
          showall = req.args.get('show') == 'all'
          milestone_list = [ m.name for m in Milestone.select(self.env, showall, db) ]
          if milestone == None:
             milestone_num = 0 
          elif milestone in milestone_list:
             milestone_num = milestone_list.find(milestone)
          else:
             milestone_num = 0

          data = {}
          data['ticket_data'] = count
          data['start_date'] = format_date(from_date)
          data['end_date'] = format_date(at_date)
          data['resolution'] = str(graph_res)
          data['baseurl'] = req.base_url
          data['milestones'] = milestone_list
          data['cmilestone'] = milestone_num
          data['yui_base_url'] = self.yui_base_url
          return 'greensauce.html', data, None
Esempio n. 39
0
    def _render_view(self, req, db):
        
        showall = req.args.get('show') == 'all'
        showmetrics = req.args.get('showmetrics') == 'true'
                
        # Get list of milestone object for the project
        milestones = list(Milestone.select(self.env, showall, db))
        stats = []
        queries = []

        self.env.log.info("getting milestones statistics")
        for milestone in milestones:
            tickets = get_tickets_for_milestone(self.env, db, milestone.name,
                                                'owner')
            stat = get_ticket_stats(self.stats_provider, tickets)
            stats.append(milestone_stats_data(self.env, req, stat, milestone.name))

        project = {
            'name': self.env.project_name,
            'description': self.env.project_description
        }
        
        data = {
            'context': Context.from_request(req),
            'milestones': milestones,
            'milestone_stats': stats,
            'queries': queries,
            'showall': showall,
            'showmetrics': showmetrics,
            'project' : project,
            'yui_base_url': self.yui_base_url 
        }
        
        self.env.log.info("getting project statistics")
        project_tickets = get_project_tickets(self.env)
        
        # Get project progress stats
        proj_stat = self.stats_provider.get_ticket_group_stats(project_tickets)
        
        data['proj_progress_stat'] = {'stats': proj_stat,
                                      'stats_href': req.href.query(proj_stat.qry_args),
                                      'interval_hrefs': [req.href.query(interval['qry_args'])
                                                         for interval in proj_stat.intervals]}

        closed_stat = self.stats_provider.get_ticket_resolution_group_stats(project_tickets)

        data['proj_closed_stat'] = {'stats': closed_stat,
                                      'stats_href': req.href.query(closed_stat.qry_args),
                                      'interval_hrefs': [req.href.query(interval['qry_args'])
                                                         for interval in closed_stat.intervals]}

        tkt_frequency_stats = {}
        tkt_duration_stats = {}
        bmi_stats = []
        daily_backlog_chart = {}
        today = datetime.now()
            
        if showmetrics:                                                     
            self.env.log.info("getting ticket metrics")
            tkt_group_metrics = TicketGroupMetrics(self.env, project_tickets)      
        
            tkt_frequency_stats = tkt_group_metrics.get_frequency_metrics_stats()
            tkt_duration_stats = tkt_group_metrics.get_duration_metrics_stats()
            
            #stat for this month
            first_day = datetime(today.year, today.month, 1, tzinfo=utc)
            last_day = last_day_of_month(today.year, today.month)
            bmi_stats.append(tkt_group_metrics.get_bmi_monthly_stats(first_day, last_day))
         
            # stat for last month        
            last_day = first_day - timedelta(days=1)
            first_day = datetime(last_day.year, last_day.month, 1, tzinfo=utc)
            bmi_stats.append(tkt_group_metrics.get_bmi_monthly_stats(first_day, last_day))
            
            # get daily backlog history
            last_day = datetime(today.year, today.month, today.day, tzinfo=utc)
            first_day = last_day - timedelta(days=DAYS_BACK)            
            self.env.log.info("getting backlog history")
            backlog_history = tkt_group_metrics.get_daily_backlog_history(first_day, last_day)
            daily_backlog_chart = tkt_group_metrics.get_daily_backlog_chart(backlog_history)

        # Get dialy commits history
        last_day = datetime(today.year, today.month, today.day, tzinfo=utc)
        first_day = last_day - timedelta(days=DAYS_BACK)
        changeset_group_stats = ChangesetsStats(self.env, first_day, last_day)
        commits_by_date = changeset_group_stats.get_commit_by_date()
        commits_by_date_chart = changeset_group_stats.get_commit_by_date_chart(commits_by_date)
        
        data['project_bmi_stats'] = bmi_stats
        #self.env.log.info(bmi_stats)
        data['ticket_frequency_stats'] = tkt_frequency_stats
        data['ticket_duration_stats'] = tkt_duration_stats
        data['ds_daily_backlog'] = daily_backlog_chart
        data['ds_commit_by_date'] = commits_by_date_chart
        
        add_stylesheet(req, 'pd/css/dashboard.css')        
        add_stylesheet(req, 'common/css/report.css')
        
        return ('pdashboard.html', data, None)
Esempio n. 40
0
 def getMilestones(self, component, req ):
     milestones = []
     for m in Milestone.select(component.env) :
         milestones.append(m.name) 
     return milestones
Esempio n. 41
0
    def _render_project_stats(self, req, data):
        project_id = req.data['project_id']

        defaults = {
            # summary
            'tkt_summary': True,
            'milestones_stats': True,
            'tkt_extra_stats': False,
            # time range
            'tkt_activity': False,
            'repos_stats': True,
            'backlog_daily': True,
            # time groups
            'repos_activity': True,
            'backlog_table': False,
            'wiki_activity': True,
        }
        metrics = self._enabled_metrics(req, defaults)

        show_completed = req.args.has_key('show_completed')

        data.update({
            'metrics': metrics,
            'show_completed': show_completed,
        })

        groupsize = data['groupsize']
        groupcnt  = data['groupcnt']
        first_day       = data['first_day']
        first_day_group = data['first_day_group']
        last_day        = data['last_day']

        db = self.env.get_read_db()

        if metrics['milestones_stats']:
            # Get list of milestone object for the project
            milestones = list(Milestone.select(self.env, project_id, show_completed, db))
            stats = []

            for milestone in milestones:
                tickets = get_tickets_for_milestone(self.env, db, milestone, 'owner')
                stat = get_ticket_stats(self.stats_provider, tickets, project_id)
                stats.append(milestone_stats_data(self.env, req, stat, milestone))

            add_stylesheet(req, 'common/css/roadmap.css')
            data.update({
                'milestones': milestones,
                'milestone_stats': stats,
            })

        project_tickets = get_project_tickets(self.env, project_id)

        if metrics['tkt_summary']:
            # Get project progress stats
            proj_stat = self.stats_provider.get_ticket_group_stats(project_tickets, project_id)

            data['proj_progress_stat'] = {'stats': proj_stat,
                                          'stats_href': req.href.query(proj_stat.qry_args, project_id=project_id),
                                          'interval_hrefs': [req.href.query(interval['qry_args'])
                                                             for interval in proj_stat.intervals]}

            closed_stat = self.stats_provider.get_ticket_resolution_group_stats(project_tickets, project_id)

            data['proj_closed_stat'] = {'stats': closed_stat,
                                        'stats_href': req.href.query(closed_stat.qry_args, project_id=project_id),
                                        'interval_hrefs': [req.href.query(interval['qry_args'])
                                                           for interval in closed_stat.intervals]}

        if metrics['backlog_daily'] or metrics['backlog_table'] or metrics['tkt_extra_stats']:
            tkt_group_metrics = TicketGroupMetrics(self.env, project_tickets)

            if metrics['tkt_extra_stats']:
                tkt_frequency_stats = tkt_group_metrics.get_frequency_metrics_stats()
                tkt_duration_stats = tkt_group_metrics.get_duration_metrics_stats()
                data.update({
                    'ticket_frequency_stats': tkt_frequency_stats,
                    'ticket_duration_stats': tkt_duration_stats,
                })

            if metrics['backlog_table']:
                bmi_stats = []
                d = first_day_group
                fday = datetime(d.year, d.month, d.day, tzinfo=req.tz)
                for _i in xrange(groupcnt):
                    lday = fday + timedelta(groupsize, microseconds=-1)
                    bstats = tkt_group_metrics.get_bmi_stats(fday, lday)
                    bmi_stats.append(('%s - %s' % (format_date(fday), format_date(lday)),) + bstats)
                    fday += timedelta(groupsize)
                data['project_bmi_stats'] = bmi_stats

            if metrics['backlog_daily']:
                # get daily backlog history
                backlog_history = tkt_group_metrics.get_daily_backlog_history(first_day, last_day)
                daily_backlog_chart = tkt_group_metrics.get_daily_backlog_chart(backlog_history)
                data['ds_daily_backlog'] = daily_backlog_chart


        if metrics['repos_stats']:
            # Get daily commits history
            changeset_group_stats = ChangesetsStats(self.env, project_id, first_day, last_day)
            commits_by_date = changeset_group_stats.get_commit_by_date()
            commits_by_date_chart = changeset_group_stats.get_commit_by_date_chart(commits_by_date)
            data['ds_commit_by_date'] = commits_by_date_chart


        data_json = {}

        if metrics['tkt_activity']:
            data['ticket_activity'] = reports.ticket_activity(project_id,
                                          first_day, last_day,
                                          db, req)
            data_json['ticket_activity'] = simplejson.dumps(data['ticket_activity'].get_data())

        if metrics['repos_activity']:
            data['repository_activity'] = reports.repository_activity(project_id,
                                              first_day_group, last_day, groupsize, groupcnt,
                                              db, req, authors_limit=self.tm.authors_limit_repos)
            data_json['repository_activity'] = simplejson.dumps(data['repository_activity'].get_data())

        if metrics['wiki_activity']:
            data['wiki_activity'] = reports.wiki_activity(project_id,
                                          first_day, last_day, groupsize, groupcnt,
                                          db, req, authors_limit=self.tm.authors_limit_wiki)
            data_json['wiki_activity'] = simplejson.dumps(data['wiki_activity'].get_data())

        data['json'] = data_json

        return ('pdashboard.html', data, None)
Esempio n. 42
0
    def process_request(self, req):
        req.perm.require('REPORT_VIEW')
        req_content = req.args.get('content')
        milestone = None

        if not None in [
                req.args.get('end_date'),
                req.args.get('start_date'),
                req.args.get('resolution')
        ]:
            # form submit
            grab_at_date = req.args.get('end_date')
            grab_from_date = req.args.get('start_date')
            grab_resolution = req.args.get('resolution')
            grab_milestone = req.args.get('milestone')
            if grab_milestone == "__all":
                milestone = None
            else:
                milestone = grab_milestone

            # validate inputs
            if None in [grab_at_date, grab_from_date]:
                raise TracError('Please specify a valid range.')

            if None in [grab_resolution]:
                raise TracError('Please specify the graph interval.')

            if 0 in [
                    len(grab_at_date),
                    len(grab_from_date),
                    len(grab_resolution)
            ]:
                raise TracError(
                    'Please ensure that all fields have been filled in.')

            if not grab_resolution.isdigit():
                raise TracError(
                    'The graph interval field must be an integer, days.')

            at_date = parse_date(grab_at_date)
            at_date = datetime.combine(at_date, time(11, 59, 59, 0,
                                                     utc))  # Add tzinfo

            from_date = parse_date(grab_from_date)
            from_date = datetime.combine(from_date, time(0, 0, 0, 0,
                                                         utc))  # Add tzinfo

            graph_res = int(grab_resolution)
        else:
            # default data
            todays_date = date.today()
            at_date = datetime.combine(todays_date, time(11, 59, 59, 0, utc))
            from_date = at_date - timedelta(self.default_days_back)
            graph_res = self.default_interval

        count = []

        db = self.env.get_db_cnx()

        # Calculate 0th point
        last_date = from_date - timedelta(graph_res)
        last_num_open = get_num_open_tix(db, last_date, milestone)

        # Calculate remaining points
        for cur_date in date_range(from_date, at_date, graph_res):
            num_open = get_num_open_tix(db, cur_date, milestone)
            num_closed = get_num_closed_tix(db, last_date, cur_date, milestone)
            date_str = format_date(cur_date)
            if graph_res != 1:
                date_str = "%s thru %s" % (format_date(last_date), date_str)
            count.append({
                'date': date_str,
                'new': num_open - last_num_open + num_closed,
                'closed': num_closed,
                'open': num_open
            })
            last_num_open = num_open
            last_date = cur_date

        # if chart data is requested, raw text is returned rather than data
        # object for templating
        if req_content is not None and req_content == "chartdata":
            js_data = '{"chartdata": [\n'
            for x in count:
                js_data += '{"date": "%s",' % x['date']
                js_data += ' "new_tickets": %s,' % x['new']
                js_data += ' "closed": %s,' % x['closed']
                js_data += ' "open": %s},\n' % x['open']
            js_data = js_data[:-2] + '\n]}'
            req.send(js_data.encode('utf-8'))
            return
        else:
            show_all = req.args.get('show') == 'all'
            milestone_list = [
                m.name for m in Milestone.select(self.env, show_all)
            ]
            if milestone in milestone_list:
                milestone_num = milestone_list.index(milestone) + 1
            else:
                milestone_num = 0

            data = {
                'ticket_data': count,
                'start_date': format_date(from_date),
                'end_date': format_date(at_date),
                'resolution': str(graph_res),
                'baseurl': req.base_url,
                'milestones': milestone_list,
                'cmilestone': milestone_num,
                'yui_base_url': self.yui_base_url,
                'debug': 'debug' in req.args
            }

            if hasattr(Chrome, 'add_jquery_ui'):
                Chrome(self.env).add_jquery_ui(req)

            return 'ticketstats.html', data, None
Esempio n. 43
0
    def _render_view(self, req, milestone):
        milestone_groups = []
        available_groups = []
        component_group_available = False
        ticket_fields = TicketSystem(self.env).get_ticket_fields()

        # collect fields that can be used for grouping
        for field in ticket_fields:
            if field['type'] == 'select' and field['name'] != 'milestone' \
                    or field['name'] in ('owner', 'reporter'):
                available_groups.append({
                    'name': field['name'],
                    'label': field['label']
                })
                if field['name'] == 'component':
                    component_group_available = True

        # determine the field currently used for grouping
        by = None
        if component_group_available:
            by = 'component'
        elif available_groups:
            by = available_groups[0]['name']
        by = req.args.get('by', by)

        tickets = get_tickets_for_milestone(self.env,
                                            milestone=milestone.name,
                                            field=by)
        tickets = apply_ticket_permissions(self.env, req, tickets)
        stat = get_ticket_stats(self.stats_provider, tickets)

        context = web_context(req, milestone.resource)
        data = {
            'context': context,
            'milestone': milestone,
            'attachments': AttachmentModule(self.env).attachment_data(context),
            'available_groups': available_groups,
            'grouped_by': by,
            'groups': milestone_groups
        }
        data.update(milestone_stats_data(self.env, req, stat, milestone.name))

        if by:
            groups = []
            for field in ticket_fields:
                if field['name'] == by:
                    if 'options' in field:
                        groups = field['options']
                        if field.get('optional'):
                            groups.insert(0, '')
                    else:
                        groups = [
                            group for group, in self.env.db_query("""
                                  SELECT DISTINCT COALESCE(%s, '') FROM ticket
                                  ORDER BY COALESCE(%s, '')
                                  """ % (by, by))
                        ]
            max_count = 0
            group_stats = []

            for group in groups:
                values = (group, ) if group else (None, group)
                group_tickets = [t for t in tickets if t[by] in values]
                if not group_tickets:
                    continue

                gstat = get_ticket_stats(self.stats_provider, group_tickets)
                if gstat.count > max_count:
                    max_count = gstat.count

                group_stats.append(gstat)

                gs_dict = {'name': group}
                gs_dict.update(
                    milestone_stats_data(self.env, req, gstat, milestone.name,
                                         by, group))
                milestone_groups.append(gs_dict)

            for idx, gstat in enumerate(group_stats):
                gs_dict = milestone_groups[idx]
                percent = 1.0
                if max_count:
                    percent = float(gstat.count) / float(max_count) * 100
                gs_dict['percent_of_max_total'] = percent

        add_stylesheet(req, 'common/css/roadmap.css')
        add_script(req, 'common/js/folding.js')

        def add_milestone_link(rel, milestone):
            href = req.href.milestone(milestone.name, by=req.args.get('by'))
            add_link(req, rel, href,
                     _('Milestone "%(name)s"', name=milestone.name))

        milestones = [
            m for m in Milestone.select(self.env)
            if 'MILESTONE_VIEW' in req.perm(m.resource)
        ]
        idx = [i for i, m in enumerate(milestones) if m.name == milestone.name]
        if idx:
            idx = idx[0]
            if idx > 0:
                add_milestone_link('first', milestones[0])
                add_milestone_link('prev', milestones[idx - 1])
            if idx < len(milestones) - 1:
                add_milestone_link('next', milestones[idx + 1])
                add_milestone_link('last', milestones[-1])
        prevnext_nav(req, _('Previous Milestone'), _('Next Milestone'),
                     _('Back to Roadmap'))

        return 'milestone_view.html', data, None
Esempio n. 44
0
    def _render_view(self, req, milestone):
        milestone_groups = []
        available_groups = []
        component_group_available = False
        ticket_fields = TicketSystem(self.env).get_ticket_fields()

        # collect fields that can be used for grouping
        for field in ticket_fields:
            if field['type'] == 'select' and field['name'] != 'milestone' \
                    or field['name'] in ('owner', 'reporter'):
                available_groups.append({'name': field['name'],
                                         'label': field['label']})
                if field['name'] == 'component':
                    component_group_available = True

        # determine the field currently used for grouping
        by = None
        if component_group_available:
            by = 'component'
        elif available_groups:
            by = available_groups[0]['name']
        by = req.args.get('by', by)

        tickets = get_tickets_for_milestone(self.env, milestone=milestone.name,
                                            field=by)
        tickets = apply_ticket_permissions(self.env, req, tickets)
        stat = get_ticket_stats(self.stats_provider, tickets)

        context = web_context(req, milestone.resource)
        data = {
            'context': context,
            'milestone': milestone,
            'attachments': AttachmentModule(self.env).attachment_data(context),
            'available_groups': available_groups, 
            'grouped_by': by,
            'groups': milestone_groups
            }
        data.update(milestone_stats_data(self.env, req, stat, milestone.name))

        if by:
            def per_group_stats_data(gstat, group_name):
                return milestone_stats_data(self.env, req, gstat, 
                                            milestone.name, by, group_name)
            milestone_groups.extend(
                grouped_stats_data(self.env, self.stats_provider, tickets, by,
                                   per_group_stats_data))

        add_stylesheet(req, 'common/css/roadmap.css')
        add_script(req, 'common/js/folding.js')

        def add_milestone_link(rel, milestone):
            href = req.href.milestone(milestone.name, by=req.args.get('by'))
            add_link(req, rel, href, _('Milestone "%(name)s"',
                                       name=milestone.name))

        milestones = [m for m in Milestone.select(self.env)
                      if 'MILESTONE_VIEW' in req.perm(m.resource)]
        idx = [i for i, m in enumerate(milestones) if m.name == milestone.name]
        if idx:
            idx = idx[0]
            if idx > 0:
                add_milestone_link('first', milestones[0])
                add_milestone_link('prev', milestones[idx - 1])
            if idx < len(milestones) - 1:
                add_milestone_link('next', milestones[idx + 1])
                add_milestone_link('last', milestones[-1])
        prevnext_nav(req, _('Previous Milestone'), _('Next Milestone'),
                     _('Back to Roadmap'))

        return 'milestone_view.html', data, None
Esempio n. 45
0
    def process_request(self, req):
        if req.path_info == '/flashgantt/chartxml':
            req.perm.require('MILESTONE_VIEW')

            showall = req.args.get('show') == 'all'

            # Get the current date and time
            cur_dt = datetime.date.today()

            # Get the quarter I am in.
            cur_quarter = self._get_quarter(cur_dt.month)
            prev_quarter = self._get_prev_quarter(cur_quarter)
            next_quarter = self._get_next_quarter(cur_quarter)

            (cq_sd, cq_ed) = self._get_quarter_start_end_dates(
                cur_dt.year, cur_quarter)
            (pq_sd, pq_ed) = self._get_prev_quarters_start_end_dates(
                cur_dt.year, cur_quarter)
            (nq_sd, nq_ed) = self._get_next_quarters_start_end_dates(
                cur_dt.year, cur_quarter)
            min_date = pq_sd.strftime('%d/%m/%Y')
            max_date = nq_ed.strftime('%d/%m/%Y')

            quarters = []
            quarters.append({
                'name':
                'Q' + str(prev_quarter) + ' ' + str(pq_sd.year),
                'start_date':
                pq_sd.strftime('%d/%m/%Y'),
                'end_date':
                pq_ed.strftime('%d/%m/%Y')
            })
            quarters.append({
                'name':
                'Q' + str(cur_quarter) + ' ' + str(cq_sd.year),
                'start_date':
                cq_sd.strftime('%d/%m/%Y'),
                'end_date':
                cq_ed.strftime('%d/%m/%Y')
            })
            quarters.append({
                'name':
                'Q' + str(next_quarter) + ' ' + str(nq_sd.year),
                'start_date':
                nq_sd.strftime('%d/%m/%Y'),
                'end_date':
                nq_ed.strftime('%d/%m/%Y')
            })

            months = []
            for x in range(pq_sd.month, (pq_ed.month + 1)):
                (cm_sd, cm_ed) = self._get_month_start_end_dates(pq_sd.year, x)
                months.append({
                    'name': self._get_month_name(x),
                    'start_date': cm_sd.strftime('%d/%m/%Y'),
                    'end_date': cm_ed.strftime('%d/%m/%Y')
                })
            for x in range(cq_sd.month, (cq_ed.month + 1)):
                (cm_sd, cm_ed) = self._get_month_start_end_dates(cq_sd.year, x)
                months.append({
                    'name': self._get_month_name(x),
                    'start_date': cm_sd.strftime('%d/%m/%Y'),
                    'end_date': cm_ed.strftime('%d/%m/%Y')
                })
            for x in range(nq_sd.month, (nq_ed.month + 1)):
                (cm_sd, cm_ed) = self._get_month_start_end_dates(nq_sd.year, x)
                months.append({
                    'name': self._get_month_name(x),
                    'start_date': cm_sd.strftime('%d/%m/%Y'),
                    'end_date': cm_ed.strftime('%d/%m/%Y')
                })

            milestones = []
            db = self.env.get_db_cnx()
            ms = [
                m for m in Milestone.select(self.env, showall, db)
                if 'MILESTONE_VIEW' in req.perm(m.resource)
            ]
            cnt = 0
            for m in ms:
                cnt = cnt + 1
                comp_stat = 0
                if (m.is_completed):
                    comp_stat = 1
                milestones.append({
                    'name':
                    m.name,
                    'id':
                    str(cnt),
                    'start_date':
                    pq_sd.strftime('%d/%m/%Y'),
                    'due_date':
                    format_date(m.due, format='%d/%m/%Y'),
                    'completed_date':
                    format_date(m.completed, format='%d/%m/%Y'),
                    'completed':
                    comp_stat
                })
            data = {
                'milestones': milestones,
                'showall': showall,
                'visible_months': months,
                'quarters': quarters
            }

            # This tuple is for Genshi (template_name, data, content_type)
            # Without data the trac layout will not appear.
            return ('chart.xml', data, 'text/xml')
        else:

            req.perm.require('MILESTONE_VIEW')

            showall = req.args.get('show') == 'all'

            db = self.env.get_db_cnx()
            milestones = [
                m for m in Milestone.select(self.env, showall, db)
                if 'MILESTONE_VIEW' in req.perm(m.resource)
            ]

            chart_height = 150 + (len(milestones) * 29)
            if (showall):
                xmlcharturl = req.href.flashgantt('/chartxml?show=all')
            else:
                xmlcharturl = req.href.flashgantt('/chartxml')

            data = {
                'milestones': milestones,
                'showall': showall,
                'xmlcharturl': xmlcharturl,
                'chart_height': chart_height
            }

            #add_stylesheet(req, 'fg/css/flashgantt.css')

            # This tuple is for Genshi (template_name, data, content_type)
            # Without data the trac layout will not appear.
            return ('flashgantt.html', data, None)
Esempio n. 46
0
    def process_request(self, req):
        req.perm.require('REPORT_VIEW')
        req_content = req.args.get('content')
        milestone = None

        if not None in [req.args.get('end_date'), req.args.get('start_date'),
                        req.args.get('resolution')]:
            # form submit
            grab_at_date = req.args.get('end_date')
            grab_from_date = req.args.get('start_date')
            grab_resolution = req.args.get('resolution')
            grab_milestone = req.args.get('milestone')
            if grab_milestone == "__all":
                milestone = None
            else:
                milestone = grab_milestone

            # validate inputs
            if None in [grab_at_date, grab_from_date]:
                raise TracError('Please specify a valid range.')

            if None in [grab_resolution]:
                raise TracError('Please specify the graph interval.')

            if 0 in [len(grab_at_date), len(grab_from_date),
                     len(grab_resolution)]:
                raise TracError(
                    'Please ensure that all fields have been filled in.')

            if not grab_resolution.isdigit():
                raise TracError(
                    'The graph interval field must be an integer, days.')

            at_date = parse_date(grab_at_date)
            at_date = datetime.combine(at_date,
                                       time(11, 59, 59, 0, utc))  # Add tzinfo

            from_date = parse_date(grab_from_date)
            from_date = datetime.combine(from_date,
                                         time(0, 0, 0, 0, utc))  # Add tzinfo

            graph_res = int(grab_resolution)
        else:
            # default data
            todays_date = date.today()
            at_date = datetime.combine(todays_date, time(11, 59, 59, 0, utc))
            from_date = at_date - timedelta(self.default_days_back)
            graph_res = self.default_interval

        count = []

        db = self.env.get_db_cnx()

        # Calculate 0th point
        last_date = from_date - timedelta(graph_res)
        last_num_open = get_num_open_tix(db, last_date, milestone)

        # Calculate remaining points
        for cur_date in date_range(from_date, at_date, graph_res):
            num_open = get_num_open_tix(db, cur_date, milestone)
            num_closed = get_num_closed_tix(db, last_date, cur_date, milestone)
            date_str = format_date(cur_date)
            if graph_res != 1:
                date_str = "%s thru %s" % (format_date(last_date), date_str)
            count.append({'date': date_str,
                          'new': num_open - last_num_open + num_closed,
                          'closed': num_closed,
                          'open': num_open})
            last_num_open = num_open
            last_date = cur_date

        # if chart data is requested, raw text is returned rather than data
        # object for templating
        if req_content is not None and req_content == "chartdata":
            js_data = '{"chartdata": [\n'
            for x in count:
                js_data += '{"date": "%s",' % x['date']
                js_data += ' "new_tickets": %s,' % x['new']
                js_data += ' "closed": %s,' % x['closed']
                js_data += ' "open": %s},\n' % x['open']
            js_data = js_data[:-2] + '\n]}'
            req.send(js_data.encode('utf-8'))
            return
        else:
            show_all = req.args.get('show') == 'all'
            milestone_list = [m.name for m in
                              Milestone.select(self.env, show_all)]
            if milestone in milestone_list:
                milestone_num = milestone_list.index(milestone) + 1
            else:
                milestone_num = 0

            data = {
                'ticket_data': count,
                'start_date': format_date(from_date),
                'end_date': format_date(at_date),
                'resolution': str(graph_res),
                'baseurl': req.base_url,
                'milestones': milestone_list,
                'cmilestone': milestone_num,
                'yui_base_url': self.yui_base_url,
                'debug': 'debug' in req.args
            }

            if hasattr(Chrome, 'add_jquery_ui'):
                Chrome(self.env).add_jquery_ui(req)

            return 'ticketstats.html', data, None