def filter_stream(self, req, method, filename, stream, data): chrome = Chrome(self.env) if req.path_info.startswith('/milestone') \ and req.args.get('action') in ['edit', 'new'] \ and 'max_level' not in data: milestone = data.get('milestone') levels = IttecoMilestoneAdminPanel(self.env).milestone_levels mydata ={'structured_milestones':StructuredMilestone.select(self.env), 'max_level': levels and len(levels)-1 or 0, 'milestone_name' : milestone and milestone.parent or None, 'field_name' : 'parent'} stream |=Transformer('//*[@id="edit"]/fieldset').append( chrome.render_template(req, 'itteco_milestones_dd.html', mydata, fragment=True)) if 'ticket' in data: tkt = data['ticket'] mydata ={ 'structured_milestones':StructuredMilestone.select(self.env), 'milestone_name': data['ticket']['milestone'], 'field_name' : 'field_milestone', 'hide_completed' : not ( tkt.exists and 'TICKET_ADMIN' in req.perm(tkt.resource)) } req.chrome.setdefault('ctxtnav',[]).insert( -1, tag.a( _('Go To Whiteboard'), href=req.href.whiteboard('team_tasks', data['ticket']['milestone'] or 'none') ) ) stream |=Transformer('//*[@id="field-milestone"]').replace( chrome.render_template(req, 'itteco_milestones_dd.html', mydata, fragment=True)) return stream
def _render_editor(self, req, db, milestone): data = { 'milestone': milestone, 'ticket': milestone.ticket, 'datefields' : self.date_fields, 'date_hint': get_date_format_hint(), 'datetime_hint': get_datetime_format_hint(), 'milestone_groups': [], 'jump_to' : req.args.get('jump_to') or referer_module(req) } if milestone.exists: req.perm(milestone.resource).require('MILESTONE_VIEW') milestones = [m for m in StructuredMilestone.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') TicketModule(self.env)._insert_ticket_data(req, milestone.ticket, data, get_reporter_id(req, 'author'), {}) self._add_tickets_report_data(milestone, req, data) context = Context.from_request(req, milestone.resource) data['attachments']=AttachmentModule(self.env).attachment_data(context) return 'itteco_milestone_edit.html', data, None
def _resolve_milestone(self, name, include_kids, show_completed): def _flatten_and_get_names(mil, include_kids, show_completed): names= [] if mil: mil = isinstance(mil, StructuredMilestone) and [mil,] or mil for m in mil: if show_completed or not m.completed: names.append(m.name) if include_kids: names.extend(_flatten_and_get_names(m.kids, include_kids, show_completed)) return names if name=='nearest': db = self.env.get_db_cnx() cursor = db.cursor() cursor.execute( 'SELECT name FROM milestone WHERE due>%s ORDER BY due LIMIT 1', \ (to_timestamp(datetime.now(utc)),)) row = cursor.fetchone() name=row and row[0] or 'none' elif name=='not_completed_milestones': return _flatten_and_get_names(StructuredMilestone.select(self.env, False), \ include_kids, show_completed) if name=='none': return '' try: mil = StructuredMilestone(self.env, name) names = _flatten_and_get_names(mil, include_kids, show_completed) if not names: names = mil.name return names except ResourceNotFound: return ''
def _render_editor(self, req, db, milestone): data = { 'milestone': milestone, 'ticket': milestone.ticket, 'datefields': self.date_fields, 'date_hint': get_date_format_hint(), 'datetime_hint': get_datetime_format_hint(), 'milestone_groups': [], 'jump_to': req.args.get('jump_to') or referer_module(req) } if milestone.exists: req.perm(milestone.resource).require('MILESTONE_VIEW') milestones = [ m for m in StructuredMilestone.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') TicketModule(self.env)._insert_ticket_data( req, milestone.ticket, data, get_reporter_id(req, 'author'), {}) self._add_tickets_report_data(milestone, req, data) context = Context.from_request(req, milestone.resource) data['attachments'] = AttachmentModule( self.env).attachment_data(context) return 'itteco_milestone_edit.html', data, None
def filter_stream(self, req, method, filename, stream, data): chrome = Chrome(self.env) if req.path_info.startswith('/milestone') \ and req.args.get('action') in ['edit', 'new'] \ and 'max_level' not in data: milestone = data.get('milestone') levels = IttecoMilestoneAdminPanel(self.env).milestone_levels mydata = { 'structured_milestones': StructuredMilestone.select(self.env), 'max_level': levels and len(levels) - 1 or 0, 'milestone_name': milestone and milestone.parent or None, 'field_name': 'parent' } stream |= Transformer('//*[@id="edit"]/fieldset').append( chrome.render_template(req, 'itteco_milestones_dd.html', mydata, fragment=True)) if 'ticket' in data: tkt = data['ticket'] mydata = { 'structured_milestones': StructuredMilestone.select(self.env), 'milestone_name': data['ticket']['milestone'], 'field_name': 'field_milestone', 'hide_completed': not (tkt.exists and 'TICKET_ADMIN' in req.perm(tkt.resource)) } req.chrome.setdefault('ctxtnav', []).insert( -1, tag.a(_('Go To Whiteboard'), href=req.href.whiteboard( 'team_tasks', data['ticket']['milestone'] or 'none'))) stream |= Transformer('//*[@id="field-milestone"]').replace( chrome.render_template(req, 'itteco_milestones_dd.html', mydata, fragment=True)) return stream
def process_request(self, req): req.perm('ticket').require('TICKET_VIEW') board_type = req.args.get('board_type', 'team_tasks') milestone = req.args.get('milestone') if board_type == 'chart_settings': return self._chart_settings(milestone) else: board_type = _get_req_param(req, 'board_type', 'team_tasks') if board_type != req.args.get('board_type'): #boardtype was not implicitly selected, let's restore previos state req.redirect(req.href.whiteboard(board_type, milestone)) add_stylesheet(req, 'common/css/roadmap.css') add_stylesheet(req, 'itteco/css/common.css') add_jscript( req, [ 'stuff/ui/ui.core.js', 'stuff/ui/ui.draggable.js', 'stuff/ui/ui.droppable.js', 'stuff/ui/ui.resizable.js', 'stuff/ui/plugins/jquery.colorbox.js', 'stuff/plugins/jquery.rpc.js', 'custom_select.js', 'whiteboard2.js' ], IttecoEvnSetup(self.env).debug ) show_closed_milestones = req.args.get('show_closed_milestones', False) scope_item, work_item = self._get_wbitems_config(board_type) structured_milestones = StructuredMilestone.select(self.env, show_closed_milestones) if board_type == 'burndown': structured_milestones, _ignore = self._get_milestones_by_level(structured_milestones, 'Sprint', True) data ={ 'structured_milestones' : structured_milestones, 'current_board_type' : board_type, 'milestone' : milestone, 'milestone_levels': IttecoEvnSetup(self.env).milestone_levels, 'stats_config': self._get_stats_config(), 'show_closed_milestones': show_closed_milestones, 'wbconfig' : { 'rpcurl' : req.href.login("xmlrpc"), 'baseurl' : req.href(), 'workitem' : work_item, 'scopeitem': scope_item, 'groups': self.ticket_groups, 'transitions': self.transitions }, 'team' : self.team_members_provider and self.team_members_provider.get_team_members() or [], 'ticket_types' : work_item['types'] or [] } return 'itteco_whiteboard2.html', data, 'text/html'
def ticket(self, req): tkt_id = req.args.get("obj_id") if tkt_id: req.perm.require("TICKET_MODIFY", Resource("ticket", tkt_id)) else: req.perm.require("TICKET_CREATE") descriptor = WhiteboardModule(self.env).get_new_ticket_descriptor( [type.name for type in Type.select(self.env)], tkt_id ) data = { "structured_milestones": StructuredMilestone.select(self.env), "resolutions": [], # val.name for val in Resolution.select(self.env)], "new_ticket_descriptor": descriptor, "action_controls": self._get_action_controls(req, descriptor["ticket"]), } return "itteco_ticket_edit.html", data, "text/html"
def milestone(self, req): mil_id = req.args.get("obj_id") if mil_id: req.perm.require("MILESTONE_MODIFY", Resource("milestone", mil_id)) else: req.perm.require("MILESTONE_CREATE") milestone = StructuredMilestone(self.env, mil_id) descriptor = WhiteboardModule(self.env).get_new_ticket_descriptor( [type.name for type in Type.select(self.env)], milestone.ticket.id ) data = { "structured_milestones": StructuredMilestone.select(self.env), "new_ticket_descriptor": descriptor, "milestone": milestone, "action_controls": self._get_action_controls(req, descriptor["ticket"]), } return "itteco_milestone_quick_edit.html", data, "text/html"
def ticket(self, req): tkt_id = req.args.get('obj_id') if tkt_id: req.perm.require('TICKET_MODIFY', Resource('ticket', tkt_id)) else: req.perm.require('TICKET_CREATE') descriptor = WhiteboardModule(self.env).get_new_ticket_descriptor( [type.name for type in Type.select(self.env)], tkt_id) data = { 'structured_milestones': StructuredMilestone.select(self.env), 'resolutions': [], #val.name for val in Resolution.select(self.env)], 'new_ticket_descriptor': descriptor, 'action_controls': self._get_action_controls(req, descriptor['ticket']), } return 'itteco_ticket_edit.html', data, 'text/html'
def milestone(self, req): mil_id = req.args.get('obj_id') if mil_id: req.perm.require('MILESTONE_MODIFY', Resource('milestone', mil_id)) else: req.perm.require('MILESTONE_CREATE') milestone = StructuredMilestone(self.env, mil_id) descriptor = WhiteboardModule(self.env).get_new_ticket_descriptor( [type.name for type in Type.select(self.env)], milestone.ticket.id) data = { 'structured_milestones': StructuredMilestone.select(self.env), 'new_ticket_descriptor': descriptor, 'milestone': milestone, 'action_controls': self._get_action_controls(req, descriptor['ticket']), } return 'itteco_milestone_quick_edit.html', data, 'text/html'
def query_stories(self, req, context): level = context.get('level') all_milestones = StructuredMilestone.select(self.env, True) mils, mils_dict = self._get_milestones_by_level(all_milestones, level, context.get('show_completed')) milestones = [mil.name for mil in mils] +[''] fields = [ 'summary', 'description', 'owner', self.scope_element_weight_field, self.work_element_weight_field ] def milestone_as_dict(milestone): res = dict([(f, milestone.ticket[f]) for f in fields]) res.update( { 'id': milestone.name, 'references': [] } ) return res empty_scope_element = {'id': '', 'summary': 'Backlog (no milestone)','references': []} roots = [empty_scope_element] + [milestone_as_dict(m) for m in mils] milestone_by_name = dict([(m['id'], m) for m in roots]) scope_tkt_types = set([t for t in IttecoEvnSetup(self.env).scope_element]) tickets, ticket_ids = self._get_tickets_graph(req, milestones, (scope_tkt_types,)) self.env.log.debug('roots ="%s"' % (roots,)) for ticket in tickets: root = milestone_by_name.get(ticket['milestone'],empty_scope_element) root['references'].append(ticket) return roots
def process_request(self, req): milestone_realm = Resource('milestone') req.perm.require('MILESTONE_VIEW') showall = req.args.get('show') == 'all' db = self.env.get_db_cnx() milestones = [m for m in StructuredMilestone.select(self.env, True, db) if 'MILESTONE_VIEW' in req.perm(m.resource)] requested_fmt = req.args.get('format') if requested_fmt == 'ics': self.render_ics(req, db, milestones) return max_level = len(IttecoEvnSetup(self.env).milestone_levels) max_level = max_level and max_level-1 or 0; current_level = int(req.args.get('mil_type', max_level)) if current_level==-1: #show all milestones regardless to the level milestones = sum([_get_milestone_with_all_kids(mil) for mil in milestones], []) else: #filter by level i =0 while i<current_level: next_level_mils = [] for m in milestones: next_level_mils.extend(m.kids) milestones = next_level_mils i+=1 calc_on = req.args.get('calc_on') ticket_group = req.args.get('ticket_group', 'all') selected_types = None if ticket_group=='scope_element': selected_types = IttecoEvnSetup(self.env).scope_element elif ticket_group=='work_element': selected_types = IttecoEvnSetup(self.env).work_element else: ticket_group = 'all' selected_type_names = [tkt_type.name for tkt_type in Type.select(self.env) if selected_types is None or tkt_type.value in selected_types] stats = [] milestones = [mil for mil in milestones if showall or not mil.is_completed] for milestone in milestones: tickets = get_tickets_for_structured_milestone( self.env, db, milestone.name, calc_on, selected_type_names) tickets = apply_ticket_permissions(self.env, req, tickets) stat = SelectionTicketGroupStatsProvider(self.env).get_ticket_group_stats(tickets, calc_on) stats.append( milestone_stats_data( req, stat, [m.name for m in _get_milestone_with_all_kids(milestone)])) if requested_fmt=='json': self._render_milestones_stats_as_json(req, milestones, stats) 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=req.args.get('show'), user=username, format='ics') add_link(req, 'alternate', icshref, _('iCalendar'), 'text/calendar', 'ics') visibility = [{'index':idx, 'label': label, 'active': idx==current_level} for idx, label in enumerate(IttecoEvnSetup(self.env).milestone_levels)] ticket_groups = [{'index':value, 'label': name, 'active': value==ticket_group} for value, name in self._ticket_groups] calculate_on = self.get_statistics_source(req.args.get('calc_on')) data = { 'milestones': milestones, 'milestone_stats': stats, 'mil_types': visibility, 'ticket_groups': ticket_groups, 'calc_on': calculate_on, 'queries': [], 'showall': showall, } self.env.log.debug('data:%s' % data) return 'itteco_roadmap.html', data, None
def process_request(self, req): milestone_realm = Resource('milestone') req.perm.require('MILESTONE_VIEW') showall = req.args.get('show') == 'all' db = self.env.get_db_cnx() milestones = [ m for m in StructuredMilestone.select(self.env, True, db) if 'MILESTONE_VIEW' in req.perm(m.resource) ] requested_fmt = req.args.get('format') if requested_fmt == 'ics': self.render_ics(req, db, milestones) return max_level = len(IttecoEvnSetup(self.env).milestone_levels) max_level = max_level and max_level - 1 or 0 current_level = int(req.args.get('mil_type', max_level)) if current_level == -1: #show all milestones regardless to the level milestones = sum( [_get_milestone_with_all_kids(mil) for mil in milestones], []) else: #filter by level i = 0 while i < current_level: next_level_mils = [] for m in milestones: next_level_mils.extend(m.kids) milestones = next_level_mils i += 1 calc_on = req.args.get('calc_on') ticket_group = req.args.get('ticket_group', 'all') selected_types = None if ticket_group == 'scope_element': selected_types = IttecoEvnSetup(self.env).scope_element elif ticket_group == 'work_element': selected_types = IttecoEvnSetup(self.env).work_element else: ticket_group = 'all' selected_type_names = [ tkt_type.name for tkt_type in Type.select(self.env) if selected_types is None or tkt_type.value in selected_types ] stats = [] milestones = [ mil for mil in milestones if showall or not mil.is_completed ] for milestone in milestones: tickets = get_tickets_for_structured_milestone( self.env, db, milestone.name, calc_on, selected_type_names) tickets = apply_ticket_permissions(self.env, req, tickets) stat = SelectionTicketGroupStatsProvider( self.env).get_ticket_group_stats(tickets, calc_on) stats.append( milestone_stats_data( req, stat, [m.name for m in _get_milestone_with_all_kids(milestone)])) if requested_fmt == 'json': self._render_milestones_stats_as_json(req, milestones, stats) 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=req.args.get('show'), user=username, format='ics') add_link(req, 'alternate', icshref, _('iCalendar'), 'text/calendar', 'ics') visibility = [{ 'index': idx, 'label': label, 'active': idx == current_level } for idx, label in enumerate( IttecoEvnSetup(self.env).milestone_levels)] ticket_groups = [{ 'index': value, 'label': name, 'active': value == ticket_group } for value, name in self._ticket_groups] calculate_on = self.get_statistics_source(req.args.get('calc_on')) data = { 'milestones': milestones, 'milestone_stats': stats, 'mil_types': visibility, 'ticket_groups': ticket_groups, 'calc_on': calculate_on, 'queries': [], 'showall': showall, } self.env.log.debug('data:%s' % data) return 'itteco_roadmap.html', data, None
def _render_admin_panel(self, req, cat, page, milestone): req.perm.require('TICKET_ADMIN') add_stylesheet(req, 'itteco/css/common.css') add_jscript( req, [ 'stuff/ui/ui.core.js', 'stuff/ui/ui.resizable.js', 'custom_select.js' ], IttecoEvnSetup(self.env).debug ) # Detail view? if milestone: mil = StructuredMilestone(self.env, milestone) if req.method == 'POST': if req.args.get('save'): mil.name = req.args.get('name') mil.due = mil.completed = None due = req.args.get('duedate', '') if due: mil.due = parse_date(due, req.tz) if req.args.get('completed', False): completed = req.args.get('completeddate', '') mil.completed = parse_date(completed, req.tz) if mil.completed > datetime.now(utc): raise TracError(_('Completion date may not be in ' 'the future'), _('Invalid Completion Date')) mil.description = req.args.get('description', '') mil.parent = req.args.get('parent', None) if mil.parent and mil.parent==mil.name: raise TracError(_('Milestone cannot be parent for itself,Please, give it another thought.'), _('Something is wrong with Parent Milestone. Will you check it please?')) if mil.parent and not StructuredMilestone(self.env, mil.parent).exists: raise TracError(_('Milestone should have a valid parent. It does not look like this is the case.'), _('Something is wrong with Parent Milestone. Will you check it please?')) mil.update() req.redirect(req.href.admin(cat, page)) elif req.args.get('cancel'): req.redirect(req.href.admin(cat, page)) add_script(req, 'common/js/wikitoolbar.js') data = {'view': 'detail', 'milestone': mil} else: if req.method == 'POST': # Add Milestone if req.args.get('add') and req.args.get('name'): name = req.args.get('name') try: StructuredMilestone(self.env, name) except ResourceNotFound: mil = StructuredMilestone(self.env) mil.name = name if req.args.get('duedate'): mil.due = parse_date(req.args.get('duedate'), req.tz) mil.parent = req.args.get('parent', None) if mil.parent and not StructuredMilestone(self.env, mil.parent).exists: raise TracError(_('Milestone should have a valid parent. It does not look like this is the case'), _('Something is wrong with Parent Milestone. Will you check it please?')) mil.insert() req.redirect(req.href.admin(cat, page)) else: raise TracError(_('Sorry, milestone %s already exists.') % name) # Remove milestone elif req.args.get('remove'): sel = req.args.get('sel') if not sel: raise TracError(_('Please, select the milestone.')) if not isinstance(sel, list): sel = [sel] db = self.env.get_db_cnx() for name in sel: mil = StructuredMilestone(self.env, name, db=db) mil.delete(db=db) db.commit() req.redirect(req.href.admin(cat, page)) # Set default milestone elif req.args.get('apply'): if req.args.get('default'): name = req.args.get('default') self.config.set('ticket', 'default_milestone', name) self.config.save() req.redirect(req.href.admin(cat, page)) data = { 'view': 'list', 'default': self.config.get('ticket', 'default_milestone'), } # Get ticket count db = self.env.get_db_cnx() cursor = db.cursor() milestones = [] structured_milestones = StructuredMilestone.select(self.env) mil_names = self._get_mil_names(structured_milestones) cursor.execute("SELECT milestone, COUNT(*) FROM ticket " "WHERE milestone IN (%s) GROUP BY milestone" % ("%s,"*len(mil_names))[:-1], mil_names) mil_tkt_quantity = {} for mil, cnt in cursor: mil_tkt_quantity[mil]=cnt data.update({ 'date_hint': get_date_format_hint(), 'milestones': [(mil, 0) for mil in structured_milestones],# we recover this anyway 'structured_milestones': structured_milestones, 'milestone_tickets_quantity': mil_tkt_quantity, 'max_milestone_level': self.milestone_levels and len(self.milestone_levels)-1 or 0, 'datetime_hint': get_datetime_format_hint() }) return 'itteco_admin_milestones.html', data