Changeset 602
- Timestamp:
- 10/17/08 14:24:34 (5 years ago)
- Location:
- trunk/plugins/tickettypedsystem/ticketsystem
- Files:
-
- 3 deleted
- 7 edited
-
api.py (modified) (7 diffs)
-
templates/ticket_layout.html (deleted)
-
templates/ticket_macros.html (deleted)
-
templates/view_ticket.html (modified) (1 diff)
-
tests/api.py (modified) (3 diffs)
-
tickettypes/__init__.py (modified) (1 diff)
-
tickettypes/oforgetickets.py (deleted)
-
tickettypes/parentticket.py (modified) (8 diffs)
-
tickettypes/uxhandler.py (modified) (3 diffs)
-
web_ui.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/plugins/tickettypedsystem/ticketsystem/api.py
r495 r602 21 21 interface changes that have to be done for specific ticket types. 22 22 """ 23 def match_for_render(self, req, data):24 """ 25 Returns True if the implementation can handle this request.23 def match_for_render(self, type): 24 """ 25 Returns True if the implementation can handle this ticket type. 26 26 """ 27 27 pass … … 75 75 class ITicketFieldProvider(Interface): 76 76 77 def get_ticket_type (self):78 """ 79 Returns the ticket type for which a implementation was built.80 """ 81 pass 82 83 def get_fields(self ):77 def get_ticket_types(self): 78 """ 79 Returns the ticket types for which a implementation was built. 80 """ 81 pass 82 83 def get_fields(self, type): 84 84 """ 85 85 Returns a list with the permitted fields. 86 """ 87 pass 88 89 def get_value(self, ticket, field_name): 90 """ 91 Returns the value for this field. 86 92 """ 87 93 pass … … 148 154 fields = list() 149 155 for filter in self.ticket_filters : 150 if ticket_type == filter.get_ticket_type():151 fields.extend(filter.get_fields( ))156 if ticket_type in filter.get_ticket_types(): 157 fields.extend(filter.get_fields(ticket_type)) 152 158 # return the filtered fields 153 159 return [field for field in original_fields if field['name'] in fields] … … 160 166 filtered = False 161 167 for filter in self.ticket_filters : 162 if ticket_type == filter.get_ticket_type():168 if ticket_type in filter.get_ticket_types(): 163 169 filtered = True 164 fields.extend(filter.get_fields( ))170 fields.extend(filter.get_fields(ticket_type)) 165 171 # return the filtered fields 166 172 if filtered : … … 179 185 fields = list() 180 186 for filter in self.ticket_filters : 181 if ticket_type == filter.get_ticket_type():182 fields.extend(filter.get_fields( ))187 if ticket_type in filter.get_ticket_types(): 188 fields.extend(filter.get_fields(ticket_type)) 183 189 # return the filtered fields names 184 190 return [field['name'] for field in original_fields if field['name'] not in fields] … … 193 199 fields = list() 194 200 for filter in self.ticket_filters : 195 if ticket_type == filter.get_ticket_type():196 fields.extend(filter.get_fields( ))201 if ticket_type in filter.get_ticket_types(): 202 fields.extend(filter.get_fields(ticket_type)) 197 203 # return the filtered fields 198 204 return [field for field in original_fields if field['name'] in fields] … … 238 244 the Ticket object. 239 245 """ 246 240 247 def __init__(self, env, tkt_id=None, db=None, version=None): 241 248 if type(tkt_id) is Ticket : 242 #self.resource = Resource('ticket', tkt_id.id, version) 243 self.parent = None 249 self.parent = tkt_id 244 250 super(TypedTicket, self).__init__(env, tkt_id.id, db, version) 245 251 else : 246 self.parent = None252 self.parent = Ticket(env, tkt_id) 247 253 super(TypedTicket, self).__init__(env, tkt_id, db, version) 248 254 self.fields = TypedTicketSystem(self.env).get_ticket_fields(self['type']) 249 255 self._old = {} 250 #self.realm= self.resource.realm251 256 252 257 def _get_typed_values(self): 253 258 # TODO: add values for the ticket relations 254 pass 259 for provider in TypedTicketSystem(self.env).ticket_filters : 260 tt = self.parent['type'] 261 for field in provider.get_fields(tt or None) : 262 self.values[field] = None 255 263 256 264 def _fetch_ticket(self, tkt_id, tkt_type=None, db=None): 257 if self.parent is None : 258 Ticket._fetch_ticket(self, tkt_id, db) 265 Ticket._fetch_ticket(self, tkt_id, db) 259 266 if type(self.parent) is Ticket : 260 self.values = self.parent.values261 267 self.time_created = self.parent.time_created 262 268 self.time_changed = self.parent.time_changed 263 269 self._get_typed_values() 264 270 271 def __getattr__(self, name) : 272 return getattr(self.parent, name) 273 265 274 def __getitem__(self, name): 266 return super(TypedTicket, self).__getitem__(name) 275 if name not in self.parent.values.keys() : 276 for provider in TypedTicketSystem(self.env).ticket_filters : 277 value = provider.get_value(self, name) 278 if value : 279 return value 280 return self.parent[name] 267 281 268 282 def __setitem__(self, name, value): 269 283 super(TypedTicket, self).__setitem__(name, value) 284 -
trunk/plugins/tickettypedsystem/ticketsystem/templates/view_ticket.html
r534 r602 3 3 py:strip=""> 4 4 5 <py:def function="render_ticket_list(tk_list, label)"> 6 <tr py:if="tk_list and len(tk_list) > 0" id=""> 7 <td style="vertical-align:top;"> 8 <label>${label}:</label></td> 9 <td> 10 <div py:for="ticket in tk_list" id="view-relations"> 11 <div id="relation${ticket.id}"> 12 <a href="${href.ticket(ticket.id)}">${system.get_resource_description(ticket, 'compact')}</a> -${system.get_resource_description(ticket, 'summary')} 13 </div> 14 <br /> 15 </div> 16 </td> 17 </tr> 18 </py:def> 19 5 20 <py:match path="//div[@id='checklist-spot']" once="true"> 6 <tr><td colspan="4"> </td></tr> 7 <tr py:if="len(subtickets) > 0" id="view-subrelations-container"> 8 <th style="vertical-align:top" ><label>Sub tickets:</label></th> 9 <td colspan="3"> 10 <div py:for="ticket in subtickets" id="view-relations"> 11 <div id="relation${ticket.id}"> 12 <a href="${href.ticket(ticket.id)}">${system.get_resource_description(ticket, 'compact')}</a> -${system.get_resource_description(ticket, 'summary')} 13 </div> 14 <br /> 15 </div> 16 </td> 17 </tr> 18 <tr py:if="len(parents) > 0" id="view-relations-container"> 19 <th style="vertical-align:top"><label>Parent ticket:</label></th> 20 <td colspan="3"> 21 <div py:for="ticket in parents" id="view-relations"> 22 <div id="relation${ticket.id}"> 23 <a href="${href.ticket(ticket.id)}">${system.get_resource_description(ticket, 'compact')}</a> -${system.get_resource_description(ticket, 'summary')} 24 </div> 25 <br /> 26 </div> 27 </td> 28 </tr> 21 <tr><td colspan="2"> </td></tr> 22 ${render_ticket_list(ticket['sub_tickets'], 'Sub Tickets')} 23 ${render_ticket_list(ticket['parent_tickets'], 'Parent Tickets')} 29 24 </py:match> 30 25 </html> -
trunk/plugins/tickettypedsystem/ticketsystem/tests/api.py
r400 r602 29 29 os.mkdir(self.env.path) 30 30 31 prop_in={'ticket.type': 'checklist, dependency', 32 'ticket.fields': 'owner, status, summary', 33 'ticket.checklist.fields': 'description, cc, keywords, estimate_hours', 34 'ticket.checklist.relations': 'child, father', 35 'ticket.checklist.child.resource': 'ticket', 36 'ticket.checklist.child': 'one-many', 37 'ticket.checklist.child.synchronize' : 'milestone, version, cc, keywords', 38 'ticket.dependency.fields': 'estimate_hours', 39 'ticket.dependency.relations': 'child', 40 'ticket.dependency.child.resources': 'ticket', 41 'ticket.dependency.child': 'one-many', 42 'ticket.dependency.child.sum' : 'estimate_hours', 43 'ticket.dependency.child.synchronize' : 'milestone, version, cc, keywords', 31 prop_in={'ticket.type': 'defect, issue', 32 'ticket.defect.fields': 'estimate_hours, actual_hours, testcase', 33 'ticket.issue.fields': 'issuetype', 34 'ticket.fields': 'id, owner, type, status, summary, description, keywords, cc, estimate_date', 44 35 } 45 36 … … 49 40 prop_in={'estimate_hours': 'text', 50 41 'estimate_hours.label': 'Estimate Hours', 51 'estimate_hours.order': '4'} 42 'estimate_hours.order': '4', 43 'estimate_date': 'text', 44 'estimate_date.label': 'Estimate Date', 45 'estimate_date.order': '1', 46 'actual_hours': 'text', 47 'actual_hours.label': 'Actual Hours', 48 'actual_hours.order': '2', 49 'testcase': 'text', 50 'testcase.label': 'Test Case', 51 'testcase.order': '3'} 52 52 # save in ini 53 53 for prop, value in prop_in.items(): … … 70 70 {'type': 'text', 'name': 'keywords', 'label': 'Keywords'}, 71 71 {'type': 'text', 'name': 'cc', 'label': 'Cc'}, 72 {'name': 'estimate_hours', 'value': u'', 'custom': True, 'label': u'Estimate Hours', 'type': u'text', 'order': 4}] 72 {'name': 'estimate_hours', 'value': u'', 'custom': True, 'label': u'Estimate Hours', 'type': u'text', 'order': 4}, 73 {'name': 'estimate_date', 'value': u'', 'custom': True, 'label': u'Estimate Date', 'type': u'text', 'order': 1}, 74 {'name': 'actual_hours', 'value': u'', 'custom': True, 'label': u'Actual Hours', 'type': u'text', 'order': 2}, 75 {'name': 'testcase', 'value': u'', 'custom': True, 'label': u'Test Case', 'type': u'text', 'order': 3},] 73 76 74 self.assertEquals(self.otsys.get_ticket_fields(' checklist'), expected_result)77 self.assertEquals(self.otsys.get_ticket_fields('defect'), expected_result) 75 78 76 79 def test_get_custom_fields(self): 77 80 self.assertEquals(self.otsys.get_custom_fields(), self.tsys.get_custom_fields()) 78 expected_result = [{'name': 'estimate_hours', 'value': u'', 'label': u'Estimate Hours', 'type': u'text', 'order': 4}] 79 self.assertEquals(self.otsys.get_custom_fields('checklist'), expected_result) 81 expected_result = [{'name': 'estimate_hours', 'value': u'', 'label': u'Estimate Hours', 'type': u'text', 'order': 4}, 82 {'name': 'estimate_date', 'value': u'', 'custom': True, 'label': u'Estimate Date', 'type': u'text', 'order': 1}, 83 {'name': 'actual_hours', 'value': u'', 'custom': True, 'label': u'Actual Hours', 'type': u'text', 'order': 2}, 84 {'name': 'testcase', 'value': u'', 'custom': True, 'label': u'Test Case', 'type': u'text', 'order': 3},] 85 self.assertEquals(self.otsys.get_custom_fields('defect'), expected_result) 80 86 81 87 def test_get_ticket(self): 82 88 t = Ticket(self.env) 83 t['type'] = ' checklist'89 t['type'] = 'defect' 84 90 t['status'] = 'new' 85 91 id = t.insert() 86 self.assertEquals(self.otsys.get_ticket(id)['status'], t['status']) 92 new_tk = self.otsys.get_ticket(id) 93 self.assertEquals(new_tk['status'], t['status']) 87 94 88 95 def test_get_ticket_types(self): 89 self.assertEquals(self.otsys.get_ticket_types(), [ 'checklist', 'dependency'])96 self.assertEquals(self.otsys.get_ticket_types(), [u'defect', u'issue']) 90 97 91 98 -
trunk/plugins/tickettypedsystem/ticketsystem/tickettypes/__init__.py
r520 r602 2 2 # 3 3 # Copyright 2008 Optaros, Inc 4 import parentticket, util, uxhandler , oforgetickets4 import parentticket, util, uxhandler -
trunk/plugins/tickettypedsystem/ticketsystem/tickettypes/parentticket.py
r536 r602 13 13 class ParentTicketRelation(Component) : 14 14 15 abstract = True 16 17 implements(ITicketFieldProvider, 18 ITicketRelationshipProvider, ITicketUIWrapper) 19 15 implements(ITicketRelationshipProvider, ITicketUIWrapper, ITicketFieldProvider) 20 16 21 17 # ITicketUIWrapper 22 23 18 def get_content_to_inject(self, req, data): 24 19 """ … … 48 43 'parents': list()}) 49 44 50 if data['ticket']['type'] == self.get_ticket_type() :45 if data['ticket']['type'] in self.get_ticket_types() : 51 46 new_data['style'] = False 52 47 … … 79 74 if ticket : 80 75 # add the values to the ticket object to survive the redirect 81 setattr(ticket, self.get_ ticket_type(), tck_list)76 setattr(ticket, self.get_relation_name(), tck_list) 82 77 else : 83 78 # add a description to be sure that a field has changed and the … … 88 83 else : 89 84 # add the relation 90 if not hasattr(ticket, self.get_ ticket_type()) :85 if not hasattr(ticket, self.get_relation_name()) : 91 86 return 92 for tck_id in getattr(ticket, self.get_ ticket_type()) :87 for tck_id in getattr(ticket, self.get_relation_name()) : 93 88 parent = TypedTicket(self.env, ticket) 94 89 self.add_relation(parent, TypedTicket(self.env, tck_id)) … … 97 92 return None 98 93 94 def match_for_render(self, type): 95 if type in self.get_ticket_types() : 96 return True 97 98 return False 99 99 100 # ITicketRelationshipProvider methods 100 101 101 def match(self, ticket): 102 102 if ticket.id is None : 103 103 return True 104 if ticket['type'] == self.get_ticket_type() :104 if ticket['type'] in self.get_ticket_types() : 105 105 return True 106 106 … … 109 109 def get_relation_name(self): 110 110 """It returns the relation name.""" 111 return self.get_ticket_type()111 return 'parent_child' 112 112 113 113 def get_supported_operations(self): … … 116 116 relationship_filters = TicketMetadataProvider(self.env) \ 117 117 .get_relationship_filters(Resource('ticket'), 118 self.get_ ticket_type())118 self.get_relation_name()) 119 119 if relationship_filters is not None : 120 120 for name in relationship_filters['ticket'].get_keys() : … … 128 128 def add_relation(self, ticket, to_ticket): 129 129 return TicketRelationshipSystem(self.env).create_relationship(ticket, \ 130 self.get_ ticket_type(), to_ticket)130 self.get_relation_name(), to_ticket) 131 131 132 132 def delete_relation(self, ticket, to_ticket): 133 133 return TicketRelationshipSystem(self.env).delete_relationship(ticket, \ 134 self.get_ticket_type(), to_ticket) 135 136 # ITicketFieldProvider methods 134 self.get_relation_name(), to_ticket) 137 135 138 def get_ticket_type(self): 139 """It returns the ticket type name. """ 140 return '' 136 def get_ticket_types(self): 137 return self.env.config.getlist('ticket-system', 'ticket.type', []) 141 138 142 def get_fields(self): 143 # get the relationships described in the ini file 144 resource_filters = TicketMetadataProvider(self.env) \ 145 .get_field_filters(Resource('ticket'), self.get_ticket_type()) 146 if resource_filters is not None : 147 return resource_filters['fields'] 139 def get_fields(self, type): 140 if type not in self.get_ticket_types() : 141 if type != None : 142 return [] 143 144 return ['sub_tickets', 'parent_tickets'] 145 146 def get_value(self, ticket, name): 147 if ticket['type'] not in self.get_ticket_types() : 148 return None 149 150 if name == 'sub_tickets' : 151 return self.get_related_tickets(ticket) 152 153 if name == 'parent_tickets' : 154 return filter(lambda x: x != None, 155 TicketRelationship.get_parent(self.env, ticket.id)) 148 156 149 157 return None 150 158 151 152 class CheckListImplementation(ParentTicketRelation) :153 """Dummy implementation"""154 # ITicketUIWrapper155 156 def match_for_render(self, req, data):157 return False158 159 def handle_request(self, req, data, content_type):160 return None161 162 # ITicketFieldProvider methods163 164 def get_ticket_type(self):165 """It returns the ticket type name."""166 return 'checklist' -
trunk/plugins/tickettypedsystem/ticketsystem/tickettypes/uxhandler.py
r574 r602 3 3 # Copyright 2008 Optaros, Inc 4 4 5 from trac.core import implements, Component 6 from trac.resource import Resource 7 5 8 from genshi.core import QName 6 9 from genshi.builder import Element, tag 7 10 8 from ticketsystem.tickettypes.parentticket import ParentTicketRelation 11 from ticketsystem.api import ITicketFieldProvider, \ 12 ITicketUIWrapper, TypedTicket, TypedTicketSystem 13 from ticketsystem.tickettypes.util import TicketMetadataProvider 9 14 10 class UXTicketHandler(ParentTicketRelation) : 11 15 class OForgeTicketHandler(Component) : 12 16 """ 13 This class adds logic for making the ticket submit buttons work. 17 This class adds logic for making the ticket submit buttons work and to 18 implement oforge ticket types. 14 19 """ 15 20 16 abstract = True21 implements(ITicketFieldProvider, ITicketUIWrapper) 17 22 18 23 # ITicketUIWrapper 19 def match_for_render(self, req, data): 20 if not data.has_key('ticket') : 21 return False 22 if data['ticket']['type'] == self.get_ticket_type() or \ 23 ('type' in req.args and req.args['type'] == self.get_ticket_type()): 24 def match_for_render(self, type): 25 if type in self.get_ticket_types() : 24 26 return True 25 26 27 return False 27 28 29 def get_content_to_inject(self, req, data): 30 return dict() 31 28 32 def process_changes(self, req, ticket): 29 33 # add in the session the redirect to new … … 38 42 new_data[field.lstrip('field')[1:]] = req.args[field] 39 43 req.redirect(req.href.newticket(**new_data)) 40 super(UXTicketHandler, self).process_changes(req, ticket)44 41 45 42 46 def handle_request(self, req, data, content_type): … … 68 72 69 73 # ITicketFieldProvider methods 70 def get_ticket_type(self): 71 return '' 74 75 def get_fields(self, type): 76 # get the relationships described in the ini file 77 resource_filters = TicketMetadataProvider(self.env) \ 78 .get_field_filters(Resource('ticket'), type) 79 if resource_filters is not None : 80 return resource_filters['fields'] 81 82 return None 83 84 def get_ticket_types(self): 85 return self.env.config.getlist('ticket-system', 'ticket.type', []) 86 87 def get_value(self, ticket, field_name): 88 return None 89 -
trunk/plugins/tickettypedsystem/ticketsystem/web_ui.py
r535 r602 12 12 from trac.web.chrome import ITemplateProvider 13 13 14 from ticketsystem.api import IOperationsProvider, ITicketRelationshipProvider, ITicketUIWrapper, TypedTicketSystem 14 from ticketsystem.api import IOperationsProvider, ITicketRelationshipProvider, ITicketUIWrapper, TypedTicketSystem, TypedTicket 15 15 16 16 class TypedTicketModule(Component): … … 45 45 # ITicketChangeListener methods 46 46 def ticket_changed(self, ticket, comment, author, old_values) : 47 for ticket_renderer in [ r for r in self.renderers if r.match(ticket)]: 47 print 'ticket changed' 48 for ticket_renderer in [ r for r in self.renderers if r.match_for_render(ticket['type'])]: 48 49 ticket_renderer.process_changes(None, ticket) 49 50 50 51 def ticket_created(self, ticket): 51 for ticket_renderer in [ r for r in self.renderers if r.match (ticket)]:52 for ticket_renderer in [ r for r in self.renderers if r.match_for_render(ticket['type'])]: 52 53 ticket_renderer.process_changes(None, ticket) 53 54 … … 57 58 # ITicketManipulator methods 58 59 def validate_ticket(self, req, ticket): 59 for ticket_renderer in [ r for r in self.renderers if r.match (ticket)]:60 for ticket_renderer in [ r for r in self.renderers if r.match_for_render(ticket['type'])]: 60 61 ticket_renderer.process_changes(req, ticket) 61 62 … … 73 74 data['fields_dict'][field]['datefield'] = \ 74 75 self.config.getbool('ticket-custom',field+'.date') 75 76 for render_handle in [ rh for rh in self.renderers if rh.match_for_render(req, data)] : 76 77 type = None 78 if data.has_key('ticket') : 79 data['ticket'] = TypedTicket(self.env, data['ticket']) 80 type = data['ticket']['type'] 81 if 'type' in req.args and req.args['type'] is not None: 82 type = req.args['type'] 83 for render_handle in [ rh for rh in self.renderers if rh.match_for_render(type)] : 77 84 data.update(render_handle.get_content_to_inject(req, data)) 78 85 79 86 for render_handle in self.renderers : 80 if render_handle.match_for_render( req, data) and 'oldpage' not in req.args:87 if render_handle.match_for_render(type) and 'oldpage' not in req.args: 81 88 page = render_handle.handle_request(req, data, content_type) 82 89 if page : … … 86 93 def pre_process_request(self, req, handler) : 87 94 match = self.typed_ticket_re.match( req.path_info ) 95 88 96 if match and req.method=='POST': 97 type = None 98 if 'id' in req.args and req.args['id'] is not None: 99 type = TypedTicket(self.env, int(req.args['id']))['type'] 100 if 'field_type' in req.args and req.args['field_type'] is not None: 101 type = req.args['field_type'] 89 102 try : 90 for ticket_renderer in self.renderers:103 for ticket_renderer in [ rh for rh in self.renderers if rh.match_for_render(type)] : 91 104 ticket_renderer.process_changes(req, None) 92 105 except Exception, e: 106 print e 93 107 self.log.error(e) 94 108 return handler
Note: See TracChangeset
for help on using the changeset viewer.
