Ticket #869: patch-customworkflow-r1098-2.diff
| File patch-customworkflow-r1098-2.diff, 31.0 KB (added by pkou <pkou at ua.fm>, 7 years ago) |
|---|
-
wiki-default/TracIni
27 27 See also: TracLogging 28 28 29 29 == [ticket] == 30 || workflow || Ticket workflow class. If not specified, it is ''trac.workflows.SimpleWorkflow'' || 30 31 || default_version || Default version for newly created tickets || 31 32 || default_severity || Default severity for newly created tickets || 32 33 || default_priority || Default priority for newly created tickets || -
setup.py
198 198 author_email="info@edgewall.com", 199 199 license=LICENSE, 200 200 url=URL, 201 packages=['trac', 'trac.upgrades', 'trac.wikimacros', 'trac.mimeviewers'], 201 packages=['trac', 'trac.upgrades', 'trac.wikimacros', 'trac.mimeviewers', 202 'trac.workflows'], 202 203 data_files=[(_p('share/trac/templates'), glob('templates/*')), 203 204 (_p('share/trac/htdocs'), glob(_p('htdocs/*.*')) + [_p('htdocs/README')]), 204 205 (_p('share/trac/htdocs/css'), glob(_p('htdocs/css/*'))), -
trac/workflows/Base.py
1 # -*- coding: iso8859-1 -*- 2 # 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2004 Pavel Kourochka <pkou@ua.fm> 5 # 6 # Trac is free software; you can redistribute it and/or 7 # modify it under the terms of the GNU General Public License as 8 # published by the Free Software Foundation; either version 2 of the 9 # License, or (at your option) any later version. 10 # 11 # Trac is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 # General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program; if not, write to the Free Software 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 # 20 # Author: Pavel Kourochka <pkou@ua.fm> 21 # 22 # Abstract workflow definition 23 24 class WorkflowBase: 25 """ 26 Generic workflow class for Trac. 27 """ 28 29 def __init__(self, env, db, user): 30 """ 31 Constructor for workflow class. 32 """ 33 self.env = env 34 self.db = db 35 self.user = user 36 37 def get_actions(self, ticket): 38 """ 39 For existing tickets only. 40 Return the list of available actions for specified ticket. 41 """ 42 raise Exception, "WorkflowBase::get_actions not implemented" 43 44 def do_action(self, ticket, action, args): 45 """ 46 For new and existing tickets. 47 Perform action on a ticket. For new tickets, action name is 'create'. 48 """ 49 raise Exception, "WorkflowBase::do_action not implemented" 50 51 def get_actions_template(self, ticket): 52 """ 53 For new and existing tickets. 54 Return the name of ClearSilver template file for the workflow. 55 Return None if no additional template is required. 56 """ 57 return None 58 59 def init_template(self, ticket, hdf): 60 """ 61 For new and existing tickets. 62 Initialize ClearSilver variables for actions template. 63 Called if get_actions_template() returns file name only. 64 """ 65 pass 66 67 def validate(self, ticket, args): 68 """ 69 For new and existing tickets. 70 Validate ticket. 71 Return list of Wiki strings that describe errors in the ticket. 72 """ 73 return [] 74 75 def on_create(self, ticket): 76 """ 77 For new tickets only. 78 Update ticket fields just before inserting the ticket into database. 79 """ 80 pass 81 82 def on_save(self, ticket): 83 """ 84 For existing tickets only. 85 Update ticket fields just before saving the ticket into database. 86 """ 87 pass -
trac/workflows/TimeTrackWorkflow.py
1 # -*- coding: iso8859-1 -*- 2 # 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2004 Pavel Kourochka <pkou@ua.fm> 5 # 6 # Trac is free software; you can redistribute it and/or 7 # modify it under the terms of the GNU General Public License as 8 # published by the Free Software Foundation; either version 2 of the 9 # License, or (at your option) any later version. 10 # 11 # Trac is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 # General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program; if not, write to the Free Software 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 # 20 # Author: Pavel Kourochka <pkou@ua.fm> 21 # 22 # Simple time tracker for any workflow 23 # 24 # Usage: 25 # 1. Add custom field for time calculation 26 # file: project-path/conf/trac.ini 27 # section: [ticket-custom] 28 # parameters: 29 # totaltime = text 30 # totaltime.label = Total time 31 # 2. Enable the workflow 32 # file: project-path/conf/trac.ini 33 # section: [ticket] 34 # parameter: 35 # workflow = trac.workflows.TimeTracWorkflow 36 # optional parameter (base workflow that is used for time tracking): 37 # timetrack_workflow = <base workflow, simple workflow by default> 38 # optional parameter (custom field name that is used for time tracking): 39 # timetrack_timefld = <custom field for time, 'totaltime' by default> 40 # optional parameter (require time tracking for every action): 41 # timetrack_required = <'yes' or 'no', default is 'no'> 42 43 from trac.workflows.Base import WorkflowBase 44 45 class TimeTrackWorkflow(WorkflowBase): 46 47 def __init__(self, env, db, user): 48 WorkflowBase.__init__(self, env, db, user) 49 50 modulename = env.get_config('ticket', 'timetrack_workflow', \ 51 'trac.workflows.SimpleWorkflow') 52 i = modulename.rfind('.') 53 if i == -1: 54 classname = modulename 55 else: 56 classname = modulename[i+1:] 57 58 module = __import__(modulename, globals(), locals(), [classname]) 59 constructor = getattr(module, classname) 60 self.workflow_proxy = constructor(env, db, user) 61 62 if not isinstance(self.workflow_proxy, WorkflowBase): 63 raise EnvironmentError, "Workflow class %s from %s must be " \ 64 "descendant of class WorkflowBase from " \ 65 "trac.workflows.base" \ 66 % (classname, modulename) 67 68 self.workflow_timefldname = env.get_config( \ 69 'ticket', 'timetrack_timefld', 'totaltime') 70 if env.get_config('ticket-custom', self.workflow_timefldname, '') \ 71 != 'text': 72 raise EnvironmentError, "TimeTrackWorkflow requires custom " \ 73 "field %s. Type of the field is 'text'" \ 74 % self.workflow_timefldname 75 self.workflow_timefld = 'custom_' + self.workflow_timefldname 76 77 self.time_required = env.get_config('ticket', 'timetrack_required', 'no') 78 79 def get_actions(self, ticket): 80 return self.workflow_proxy.get_actions(ticket) 81 82 def do_action(self, ticket, action, args): 83 self.workflow_proxy.do_action(ticket, action, args) 84 85 curtime = ticket[self.workflow_timefld] or '0' 86 delta = args.get('time_delta') or '0' 87 try: 88 ticket[self.workflow_timefld] = \ 89 str(int(curtime, 10) + int(delta, 10)) 90 except: 91 self.env.log.warning('TimeTrackWorkflow: invalid time data') 92 93 def get_actions_template(self, ticket): 94 return 'ticket_workflow_timetrack.cs' 95 96 def init_template(self, ticket, hdf): 97 proxytpl = self.workflow_proxy.get_actions_template(ticket) 98 if proxytpl: 99 self.workflow_proxy.init_template(ticket, hdf) 100 hdf.setValue('ticket.workflow.proxy_template', proxytpl) 101 102 def validate(self, ticket, args): 103 err = self.workflow_proxy.validate(ticket, args) 104 105 curtimestr = ticket[self.workflow_timefld] 106 try: 107 curtime = int(curtimestr or '0', 10) 108 except: 109 curtime = -1 110 if curtime < 0: 111 err.append("Total time (custom field '''%s''') must be " \ 112 "non-negative decimal number. Value '{{{%s}}}' " \ 113 "is incorrect." % (self.workflow_timefldname, \ 114 curtimestr)) 115 116 deltastr = args.get('time_delta') 117 try: 118 delta = int(deltastr or '0', 10) 119 except: 120 delta = -1 121 if delta < 0: 122 err.append("Time that is spent on an action must be " \ 123 "non-negative decimal number. Value '{{{%s}}}' " \ 124 "is incorrect." % deltastr) 125 126 if self.time_required == 'yes' and not deltastr: 127 err.append("Time that is spent on an action must be entered.") 128 129 return err 130 131 def on_create(self, ticket): 132 self.workflow_proxy.on_create(ticket) 133 134 def on_save(self, ticket): 135 self.workflow_proxy.on_save(ticket) -
trac/workflows/__init__.py
Property changes on: trac/workflows/TimeTrackWorkflow.py ___________________________________________________________________ Name: svn:eol-style + native
1 __all__ = ['Base', 'SimpleWorkflow', 'TimeTrackWorkflow'] -
trac/workflows/SimpleWorkflow.py
1 # -*- coding: iso8859-1 -*- 2 # 3 # Copyright (C) 2003, 2004 Edgewall Software 4 # Copyright (C) 2003, 2004 Jonas Borgström <jonas@edgewall.com> 5 # 6 # Trac is free software; you can redistribute it and/or 7 # modify it under the terms of the GNU General Public License as 8 # published by the Free Software Foundation; either version 2 of the 9 # License, or (at your option) any later version. 10 # 11 # Trac is distributed in the hope that it will be useful, 12 # but WITHOUT ANY WARRANTY; without even the implied warranty of 13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 # General Public License for more details. 15 # 16 # You should have received a copy of the GNU General Public License 17 # along with this program; if not, write to the Free Software 18 # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 # 20 # Author: Pavel Kourochka <pkou@ua.fm> 21 # 22 # Simple workflow definition (as in Trac 0.8) 23 24 from trac.workflows.Base import WorkflowBase 25 26 class SimpleWorkflow(WorkflowBase): 27 28 def get_actions(self, ticket): 29 actions = { 30 'new': ['leave', 'resolve', 'reassign', 'accept'], 31 'assigned': ['leave', 'resolve', 'reassign' ], 32 'reopened': ['leave', 'resolve', 'reassign' ], 33 'closed': ['leave', 'reopen'] 34 } 35 return actions.get(ticket['status'], ['leave']) 36 37 def do_action(self, ticket, action, args): 38 if action == 'accept': 39 ticket['status'] = 'assigned' 40 ticket['owner'] = self.user 41 elif action == 'resolve': 42 ticket['status'] = 'closed' 43 ticket['resolution'] = args.get('resolve_resolution') 44 elif action == 'reassign': 45 ticket['owner'] = args.get('reassign_owner') 46 ticket['status'] = 'new' 47 elif action == 'reopen': 48 ticket['status'] = 'reopened' 49 ticket['resolution'] = '' 50 51 def get_actions_template(self, ticket): 52 if ticket.has_key('id'): 53 return 'ticket_workflow_simple.cs' 54 else: 55 return None 56 57 def init_template(self, ticket, hdf): 58 WorkflowBase.init_template(self, ticket, hdf) 59 if ticket.has_key('id'): 60 for a in self.get_actions(ticket): 61 hdf.setValue('ticket.workflow.action.' + a, '1') 62 63 def validate(self, ticket, args): 64 err = WorkflowBase.validate(self, ticket, args) 65 if not ticket.get('summary'): 66 err.append("The ticket must contain '''Summary''' field.") 67 return err 68 69 def on_create(self, ticket): 70 WorkflowBase.on_create(self, ticket) 71 72 # The owner field defaults to the component owner 73 cursor = self.db.cursor() 74 if ticket.get('owner', '') == '': 75 cursor.execute('SELECT owner FROM component ' 76 'WHERE name=%s', ticket.get('component', '')) 77 ticket['owner'] = cursor.fetchone()[0] or '' 78 79 def on_save(self, ticket): 80 WorkflowBase.on_save(self, ticket) 81 if not ticket._old: return # Not modified 82 83 # If the component is changed on a 'new' ticket then owner field 84 # is updated accordingly. (#623). 85 cursor = self.db.cursor() 86 if ticket['status'] == 'new' and ticket._old.has_key('component') and \ 87 not ticket._old.has_key('owner'): 88 cursor.execute('SELECT owner FROM component ' 89 'WHERE name=%s', ticket._old['component']) 90 old_owner = cursor.fetchone()[0] 91 if ticket['owner'] == old_owner: 92 cursor.execute('SELECT owner FROM component ' 93 'WHERE name=%s', ticket['component']) 94 ticket['owner'] = cursor.fetchone()[0] or '' -
trac/Ticket.py
130 130 131 131 if not self._old and not comment: return # Not modified 132 132 133 # If the component is changed on a 'new' ticket then owner field134 # is updated accordingly. (#623).135 if self['status'] == 'new' and self._old.has_key('component') and \136 not self._old.has_key('owner'):137 cursor.execute('SELECT owner FROM component '138 'WHERE name=%s', self._old['component'])139 old_owner = cursor.fetchone()[0]140 if self['owner'] == old_owner:141 cursor.execute('SELECT owner FROM component '142 'WHERE name=%s', self['component'])143 self['owner'] = cursor.fetchone()[0]144 145 146 133 for name in self._old.keys(): 147 134 if name[:7] == 'custom_': 148 135 fname = name[7:] … … 264 251 i += 1 265 252 266 253 254 def get_workflow(env, db, user): 255 # from trac.workflows.Simple import SimpleWorkflow 256 # return SimpleWorkflow(env, db, user) 257 modulename = env.get_config('ticket', 'workflow', \ 258 'trac.workflows.SimpleWorkflow') 259 i = modulename.rfind('.') 260 if i == -1: 261 classname = modulename 262 else: 263 classname = modulename[i+1:] 264 265 module = __import__(modulename, globals(), locals(), [classname]) 266 constructor = getattr(module, classname) 267 workflow = constructor(env, db, user) 268 269 from workflows.Base import WorkflowBase 270 if not isinstance(workflow, WorkflowBase): 271 raise EnvironmentError, "Workflow class %s from %s must be " \ 272 "descendant of class WorkflowBase from " \ 273 "trac.workflows.base" \ 274 % (classname, modulename) 275 276 return workflow 277 278 267 279 class NewticketModule(Module): 268 280 template_name = 'newticket.cs' 269 281 270 def create_ticket(self): 271 if not self.args.get('summary'): 272 raise util.TracError('Tickets must contain Summary.') 273 274 ticket = Ticket() 275 ticket.populate(self.args) 282 def create_ticket(self, ticket, workflow): 276 283 ticket.setdefault('reporter',self.req.authname) 277 284 278 # The owner field defaults to the component owner 279 cursor = self.db.cursor() 280 if ticket.get('component') and ticket.get('owner', '') == '': 281 cursor.execute('SELECT owner FROM component ' 282 'WHERE name=%s', ticket['component']) 283 owner = cursor.fetchone()[0] 284 ticket['owner'] = owner 285 285 workflow.on_create(ticket) 286 286 tktid = ticket.insert(self.db) 287 287 288 288 # Notify … … 294 294 def render (self): 295 295 self.perm.assert_permission(perm.TICKET_CREATE) 296 296 297 if self.args.has_key('create'): 298 self.create_ticket() 297 ticket = Ticket() 299 298 300 ticket = Ticket() 299 preview = self.args.has_key('preview') 300 do_create = self.args.has_key('create') 301 301 ticket.populate(self.args) 302 303 workflow = get_workflow(self.env, self.db, self.req.authname) 304 305 # Validate the ticket 306 err = [] 307 if preview or do_create: 308 err.extend(workflow.validate(ticket, self.args)) 309 if len(err) != 0: preview = 1 310 311 # Create the ticket if not in preview mode 312 if not preview and do_create: 313 workflow.do_action(ticket, 'create', self.args) 314 self.create_ticket(ticket, workflow) 315 302 316 ticket.setdefault('component', 303 317 self.env.get_config('ticket', 'default_component')) 304 318 ticket.setdefault('milestone', … … 320 334 evals = util.mydict(zip(ticket.keys(), 321 335 map(lambda x: util.escape(x), ticket.values()))) 322 336 util.add_to_hdf(evals, self.req.hdf, 'newticket') 337 if len(err) != 0: 338 self.req.hdf.setValue('newticket.workflow.error', 339 wiki_to_html(' * ' + '\n * '.join(err), 340 self.req.hdf, self.env, self.db)) 341 tpl = workflow.get_actions_template(ticket) 342 if tpl: 343 self.req.hdf.setValue('newticket.workflow.template', tpl) 344 workflow.init_template(ticket, self.req.hdf) 323 345 324 346 util.sql_to_hdf(self.db, 'SELECT name FROM component ORDER BY name', 325 347 self.req.hdf, 'newticket.components') … … 334 356 class TicketModule (Module): 335 357 template_name = 'ticket.cs' 336 358 337 def save_changes (self, id):359 def save_changes (self, ticket, workflow): 338 360 self.perm.assert_permission (perm.TICKET_MODIFY) 339 ticket = Ticket(self.db, id)340 361 341 if not self.args.get('summary'):342 raise util.TracError('Tickets must contain Summary.')343 344 362 if self.args.has_key('description'): 345 363 self.perm.assert_permission (perm.TICKET_ADMIN) 346 364 347 365 if self.args.has_key('reporter'): 348 366 self.perm.assert_permission (perm.TICKET_ADMIN) 349 367 350 # TODO: this should not be hard-coded like this351 action = self.args.get('action', None)352 if action == 'accept':353 ticket['status'] = 'assigned'354 ticket['owner'] = self.req.authname355 if action == 'resolve':356 ticket['status'] = 'closed'357 ticket['resolution'] = self.args.get('resolve_resolution')358 elif action == 'reassign':359 ticket['owner'] = self.args.get('reassign_owner')360 ticket['status'] = 'new'361 elif action == 'reopen':362 ticket['status'] = 'reopened'363 ticket['resolution'] = ''364 365 ticket.populate(self.args)366 367 368 now = int(time.time()) 368 369 370 workflow.on_save(ticket) 369 371 ticket.save_changes(self.db, 370 372 self.args.get('author', self.req.authname), 371 373 self.args.get('comment'), … … 373 375 374 376 tn = TicketNotifyEmail(self.env) 375 377 tn.notify(ticket, newticket=0, modtime=now) 376 self.req.redirect(self.env.href.ticket( id))378 self.req.redirect(self.env.href.ticket(ticket['id'])) 377 379 378 380 def insert_ticket_data(self, hdf, id, ticket, reporter_id): 379 381 """Insert ticket data into the hdf""" … … 431 433 def render (self): 432 434 self.perm.assert_permission (perm.TICKET_VIEW) 433 435 434 action = self.args.get('action', 'view')435 preview = self.args.has_key('preview')436 437 436 if not self.args.has_key('id'): 438 437 self.req.redirect(self.env.href.wiki()) 439 438 440 439 id = int(self.args.get('id')) 440 ticket = Ticket(self.db, id) 441 441 442 if not preview \ 443 and action in ['leave', 'accept', 'reopen', 'resolve', 'reassign']: 444 self.save_changes (id) 442 action = self.args.get('action', None) 443 preview = self.args.has_key('preview') 444 if action or preview: 445 ticket.populate(self.args) 445 446 446 ticket = Ticket(self.db, id) 447 workflow = get_workflow(self.env, self.db, self.req.authname) 448 449 # Validate ticket 450 err = [] 451 if action or preview: 452 actions = workflow.get_actions(ticket) 453 if action not in actions: 454 err.append("Invalid action '''%s''' is performed on the ticket. " \ 455 "Allowed actions are <''%s''>." % \ 456 (action, ', '.join(actions))) 457 err.extend(workflow.validate(ticket, self.args)) 458 if len(err) != 0: preview = 1 459 460 # Save changes if not in preview mode 461 if not preview and action: 462 workflow.do_action(ticket, action, self.args) 463 self.save_changes(ticket, workflow) 464 447 465 reporter_id = util.get_reporter_id(self.req) 448 466 449 467 if preview: 450 # Use user supplied values 451 for field in Ticket.std_fields: 452 if self.args.has_key(field) and field != 'reporter': 453 ticket[field] = self.args.get(field) 454 self.req.hdf.setValue('ticket.action', action) 468 if action: self.req.hdf.setValue('ticket.action', action) 455 469 reporter_id = self.args.get('author') 456 470 comment = self.args.get('comment') 457 471 if comment: … … 462 476 self.req.hdf, self.env, self.db)) 463 477 464 478 self.insert_ticket_data(self.req.hdf, id, ticket, reporter_id) 479 if len(err) != 0: 480 self.req.hdf.setValue('ticket.workflow.error', 481 wiki_to_html(' * ' + '\n * '.join(err), 482 self.req.hdf, self.env, self.db)) 483 tpl = workflow.get_actions_template(ticket) 484 if tpl: 485 self.req.hdf.setValue('ticket.workflow.template', tpl) 486 workflow.init_template(ticket, self.req.hdf) 465 487 466 488 cursor = self.db.cursor() 467 489 cursor.execute("SELECT max(id) FROM ticket") -
templates/ticket_workflow_timetrack.cs
1 <?cs 2 if ticket.workflow.proxy_template ?><?cs 3 include ticket.workflow.proxy_template ?><?cs 4 /if ?> 5 6 <div> 7 <label for="time_delta">action time:</label> 8 <input type="text" id="time_delta" name="time_delta" size="10" 9 value="<?cs var args.time_delta ?>" /> 10 </div> -
templates/ticket.cs
Property changes on: templates/ticket_workflow_timetrack.cs ___________________________________________________________________ Name: svn:eol-style + native
203 203 </div><?cs /if ?> 204 204 </fieldset> 205 205 206 <fieldset id="action"> 207 <legend>Action</legend><?cs 208 if:!ticket.action ?><?cs set:ticket.action = 'leave' ?><?cs 209 /if ?><?cs 210 def:action_radio(id) ?> 211 <input type="radio" id="<?cs var:id ?>" name="action" value="<?cs 212 var:id ?>"<?cs if:$ticket.action == $id ?> checked="checked"<?cs 213 /if ?> /><?cs 214 /def ?> 215 <?cs call:action_radio('leave') ?> 216 <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs 217 if $ticket.status == "new" ?> 218 <?cs call:action_radio('accept') ?> 219 <label for="accept">accept ticket</label><br /><?cs 220 /if ?><?cs 221 if $ticket.status == "closed" ?> 222 <?cs call:action_radio('reopen') ?> 223 <label for="reopen">reopen ticket</label><br /><?cs 224 /if ?><?cs 225 if $ticket.status == "new" || $ticket.status == "assigned" || $ticket.status == "reopened" ?> 226 <?cs call:action_radio('resolve') ?> 227 <label for="resolve">resolve</label> 228 <label for="resolve_resolution">as:</label> 229 <?cs call:hdf_select(enums.resolution, "resolve_resolution", args.resolve_resolution) ?><br /> 230 <?cs call:action_radio('reassign') ?> 231 <label for="reassign">reassign</label> 232 <label for="reassign_owner">to:</label> 233 <input type="text" id="reassign_owner" name="reassign_owner" size="40" value="<?cs 234 if:args.reassign_to ?><?cs var:args.reassign_to ?><?cs 235 else ?><?cs var:trac.authname ?><?cs /if ?>" /><?cs 236 /if ?><?cs 237 if $ticket.status == "new" || $ticket.status == "assigned" || $ticket.status == "reopened" ?> 238 <script type="text/javascript"> 239 var resolve = document.getElementById("resolve"); 240 var reassign = document.getElementById("reassign"); 241 var updateActionFields = function() { 242 enableControl('resolve_resolution', resolve.checked); 243 enableControl('reassign_owner', reassign.checked); 244 }; 245 addEvent(window, 'load', updateActionFields); 246 addEvent(document.getElementById("leave"), 'click', updateActionFields);<?cs 247 if $ticket.status == "new" ?> 248 addEvent(document.getElementById("accept"), 'click', updateActionFields);<?cs 249 /if ?> 250 addEvent(resolve, 'click', updateActionFields); 251 addEvent(reassign, 'click', updateActionFields); 252 </script><?cs 253 /if ?> 254 </fieldset> 206 <?cs if ticket.workflow.template ?> 207 <fieldset id="action"> 208 <legend>Action</legend> 209 <?cs include ticket.workflow.template ?> 210 </fieldset> 211 <?cs /if ?> 255 212 213 <?cs if ticket.workflow.error ?> 214 <div class="system-message"> 215 <h2>Ticket Error</h2> 216 <p class="message"><?cs var ticket.workflow.error ?></p> 217 <strong>The ticket will not be saved.</strong> 218 </div> 219 <?cs /if ?> 220 256 221 <script type="text/javascript" src="<?cs 257 222 var:htdocs_location ?>js/wikitoolbar.js"></script> 258 223 -
templates/ticket_workflow_simple.cs
1 <?cs 2 if !ticket.action ?><?cs 3 set:ticket.action = 'leave' ?><?cs 4 /if ?><?cs 5 def action_radio(id) ?> 6 <input type="radio" id="<?cs var id ?>" name="action" value="<?cs var id ?>" 7 <?cs if $ticket.action == $id ?> checked="checked"<?cs /if ?> /><?cs 8 /def ?> 9 10 <?cs 11 if ticket.workflow.action.leave ?><?cs 12 call:action_radio('leave') ?> 13 <label for="leave">leave as <?cs var:ticket.status ?></label><br /><?cs 14 /if ?><?cs 15 if ticket.workflow.action.accept ?><?cs 16 call action_radio('accept') ?> 17 <label for="accept">accept ticket</label><br /><?cs 18 /if ?><?cs 19 if ticket.workflow.action.resolve ?><?cs 20 call:action_radio('resolve') ?> 21 <label for="resolve">resolve</label> 22 <label for="resolve_resolution">as:</label><?cs 23 call:hdf_select(enums.resolution, "resolve_resolution", 24 args.resolve_resolution) ?><br /><?cs 25 /if ?><?cs 26 if ticket.workflow.action.reopen ?><?cs 27 call:action_radio('reopen') ?> 28 <label for="reopen">reopen ticket</label><br /><?cs 29 /if ?><?cs 30 if ticket.workflow.action.reassign ?><?cs 31 call:action_radio('reassign') ?> 32 <label for="reassign">reassign</label> 33 <label for="reassign_owner">to:</label> 34 <input type="text" id="reassign_owner" name="reassign_owner" size="40" 35 value=<?cs if args.reassign_to ?>"<?cs var:args.reassign_to ?>" 36 <?cs else ?>"<?cs var:trac.authname ?>" 37 <?cs /if ?> /><?cs 38 /if ?> 39 40 <?cs 41 if ticket.workflow.action.resolve || ticket.workflow.action.reassign ?> 42 <script type="text/javascript"><?cs 43 if ticket.workflow.action.resolve ?> 44 var resolve = document.getElementById("resolve");<?cs 45 /if ?><?cs 46 if ticket.workflow.action.reassign ?> 47 var reassign = document.getElementById("reassign");<?cs 48 /if ?> 49 var updateActionFields = function() {<?cs 50 if ticket.workflow.action.resolve ?> 51 enableControl('resolve_resolution', resolve.checked);<?cs 52 /if ?><?cs 53 if ticket.workflow.action.reassign ?> 54 enableControl('reassign_owner', reassign.checked);<?cs 55 /if ?> 56 }; 57 addEvent(window, 'load', updateActionFields);<?cs 58 if ticket.workflow.action.leave ?> 59 addEvent(document.getElementById("leave"), 'click', updateActionFields);<?cs 60 /if ?><?cs 61 if ticket.workflow.action.accept ?> 62 addEvent(document.getElementById("accept"), 'click', updateActionFields);<?cs 63 /if ?><?cs 64 if ticket.workflow.action.resolve ?> 65 addEvent(resolve, 'click', updateActionFields);<?cs 66 /if ?><?cs 67 if ticket.workflow.action.reopen ?> 68 addEvent(document.getElementById("reopen"), 'click', updateActionFields);<?cs 69 /if ?><?cs 70 if ticket.workflow.action.reassign ?> 71 addEvent(reassign, 'click', updateActionFields);<?cs 72 /if ?> 73 </script> 74 <?cs /if ?> -
templates/newticket.cs
69 69 </div><?cs /if ?> 70 70 </fieldset> 71 71 72 <?cs if newticket.workflow.template ?> 73 <fieldset id="action"> 74 <legend>Action</legend> 75 <?cs include newticket.workflow.template ?> 76 </fieldset> 77 <?cs /if ?> 78 79 <?cs if newticket.workflow.error ?> 80 <div class="system-message"> 81 <h2>Ticket Error</h2> 82 <p class="message"><?cs var newticket.workflow.error ?></p> 83 <strong>The ticket will not be created.</strong> 84 </div> 85 <?cs /if ?> 86 72 87 <script type="text/javascript" src="<?cs 73 88 var:htdocs_location ?>js/wikitoolbar.js"></script> 74 89 75 90 <div class="buttons"> 76 <input type="submit" value="Preview" /> 91 <input type="submit" name="preview" value="Preview" /> 77 92 <input type="submit" name="create" value="Submit ticket" /> 78 93 </div> 79 94 </form>
