Ticket #1749: ticketdelete-trac0.11-v2.patch
| File ticketdelete-trac0.11-v2.patch, 13.3 kB (added by s0undt3ch, 1 year ago) |
|---|
-
ticketdelete/web_ui.py
old new 1 1 # Ticket deleting plugins 2 2 3 3 from trac import __version__ as TRAC_VERSION 4 from trac import ticket5 4 from trac.core import * 5 from trac.ticket.model import Ticket 6 6 from trac.web.api import IRequestFilter 7 7 from trac.web.chrome import ITemplateProvider, add_script, add_stylesheet 8 from webadmin.web_ui import IAdminPageProvider8 from trac.admin.web_ui import IAdminPanelProvider 9 9 import re, traceback, pprint 10 10 from time import strftime, localtime 11 11 … … 14 14 class TicketDeletePlugin(Component): 15 15 """A small ticket deletion plugin.""" 16 16 17 implements(ITemplateProvider, IAdminPa geProvider, IRequestFilter)17 implements(ITemplateProvider, IAdminPanelProvider, IRequestFilter) 18 18 19 19 # IRequestFilter methods 20 20 def pre_process_request(self, req, handler): 21 21 return handler 22 22 23 def post_process_request(self, req, template, content_type): 24 if template == 'ticket.cs' and req.perm.has_permission('TICKET_ADMIN'): 25 add_script(req, 'ticketdelete/jquery.js') 23 def post_process_request(self, req, template, data, content_type): 24 if template == 'ticket.html' and req.perm.has_permission('TICKET_ADMIN'): 25 major, minor = self._get_trac_version() 26 if major <= 0 and minor < 11: 27 add_script(req, 'ticketdelete/jquery.js') 26 28 add_script(req, 'ticketdelete/ticketdelete.js') 27 29 add_stylesheet(req, 'ticketdelete/ticketdelete.css') 28 return template, content_type30 return template, data, content_type 29 31 30 # IAdminPa geProvider methods31 def get_admin_pa ges(self, req):32 # IAdminPanelProvider methods 33 def get_admin_panels(self, req): 32 34 if req.perm.has_permission('TICKET_ADMIN'): 33 35 yield ('ticket', 'Ticket System', 'delete', 'Delete') 34 36 yield ('ticket', 'Ticket System', 'comments', 'Delete Changes') 35 37 36 def process_admin_request(self, req, cat, page, path_info):38 def render_admin_panel(self, req, cat, page, path_info): 37 39 req.perm.assert_permission('TICKET_ADMIN') 38 40 39 data = {} 41 data={} 42 ticketdelete = {} 43 ticketdelete['href'] = req.href('admin', cat, page) 44 ticketdelete['page'] = page 45 ticketdelete['redir'] = 1 40 46 41 data['ticketdelete.href'] = req.href('admin', cat, page)42 data['ticketdelete.page'] = page43 data['ticketdelete.redir'] = 144 45 47 if req.method == 'POST': 46 48 if page == 'delete': 47 49 if 'ticketid' in req.args and 'ticketid2' in req.args: 48 50 if req.args.get('ticketid') == req.args.get('ticketid2'): 49 t = self._validate(req, req.args.get('ticketid'))51 t, ticketdelete = self._validate(req, req.args.get('ticketid'), data) 50 52 if t: 51 53 self._delete_ticket(t.id) 52 data['ticketdelete.message'] = "Ticket #%s has been deleted." % t.id54 ticketdelete['message'] = "Ticket #%s has been deleted." % t.id 53 55 54 56 else: 55 data['ticketdelete.message'] = "The two IDs did not match. Please try again."57 ticketdelete['message'] = "The two IDs did not match. Please try again." 56 58 elif page == 'comments': 57 59 if 'ticketid' in req.args: 58 60 req.redirect(req.href.admin(cat, page, req.args.get('ticketid'))) 59 61 else: 60 t = self._validate(req, path_info)62 t, ticketdelete = self._validate(req, path_info, ticketdelete) 61 63 if t: 62 data['ticketdelete.href'] = req.href('admin', cat, page, path_info)64 ticketdelete['href'] = req.href('admin', cat, page, path_info) 63 65 try: 64 66 deletions = None 65 67 if "multidelete" in req.args: … … 74 76 ts = int(ts) 75 77 self.log.debug('TicketDelete: Deleting change to ticket %s at %s (%s)'%(t.id,ts,field)) 76 78 self._delete_change(t.id, ts, field) 77 data['ticketdelete.message'] = "Change to ticket #%s at %s has been modified" % (t.id, strftime('%a, %d %b %Y %H:%M:%S',localtime(ts)))78 data['ticketdelete.redir'] = 079 ticketdelete['message'] = "Change to ticket #%s at %s has been modified" % (t.id, strftime('%a, %d %b %Y %H:%M:%S',localtime(ts))) 80 ticketdelete['redir'] = 0 79 81 except ValueError, e: 80 82 self.log.debug("TicketDelete: Error is %s"%e) 81 83 self.log.debug("TicketDelete: args = '%s'"%req.args.items()) 82 data['ticketdelete.message'] = "Timestamp '%s' not valid" % req.args.get('ts')84 ticketdelete['message'] = "Timestamp '%s' not valid" % req.args.get('ts') 83 85 84 86 85 87 if path_info: 86 t = self._validate(req, path_info)88 t, ticketdelete = self._validate(req, path_info, ticketdelete) 87 89 if t: 88 90 if page == 'comments': 89 91 try: … … 96 98 data = ticket_data.setdefault(str(time), {}) 97 99 data.setdefault('fields', {})[field] = {'old': oldvalue, 'new': newvalue} 98 100 data['author'] = author 99 data['prettytime'] = strftime('%a, %d %b %Y %H:%M:%S',localtime(time))101 #data['prettytime'] = strftime('%a, %d %b %Y %H:%M:%S',localtime(0.10)) 100 102 101 103 # Remove all attachment changes 102 104 for k, v in ticket_data.items(): … … 107 109 time_list = list(sorted(ticket_data.iterkeys())) 108 110 if selected is not None and selected < len(time_list): 109 111 ticket_data[time_list[selected]]['checked'] = True 110 data['ticketdelete.changes'] = ticket_data 112 ticketdelete['changes'] = [] 113 for time in time_list: 114 ticketdelete['changes'].append(ticket_data[time]) 111 115 elif page == 'delete': 112 data['ticketdelete.id'] = t.id116 ticketdelete['id'] = t.id 113 117 114 return 'ticketdelete_admin.html', data, None 118 #data = {'ticketdelete': ticketdelete} 119 data['ticketdelete'] = ticketdelete 115 120 121 return 'ticketdelete_admin.html', data 122 116 123 # ITemplateProvider methods 117 124 def get_templates_dirs(self): 118 125 """ … … 145 152 else: 146 153 return (0,0) 147 154 148 def _validate(self, req, arg ):155 def _validate(self, req, arg, ticketdelete): 149 156 """Validate that arg is a string containing a valid ticket ID.""" 150 157 try: 151 158 id = int(arg) 152 159 t = Ticket(self.env, id) 153 return t 160 return t, ticketdelete 154 161 except TracError: 155 data['ticketdelete.message'] = "Ticket #%s not found. Please try again." % id162 ticketdelete['message'] = "Ticket #%s not found. Please try again." % id 156 163 except ValueError: 157 data['ticketdelete.message'] = "Ticket ID '%s' is not valid. Please try again." % arg158 return False 164 ticketdelete['message'] = "Ticket ID '%s' is not valid. Please try again." % arg 165 return False, ticketdelete 159 166 160 167 161 168 def _delete_ticket(self, id): -
ticketdelete/htdocs/ticketdelete.js
old new 7 7 } else { 8 8 $('#ticket table.properties').after('<div class="description"><h3><span class="inlinebuttons">'+delete_link+'</span> </h3></div>'); 9 9 } 10 $('#changelog h3').each(function() { 10 $('#changelog form').each(function() { 11 if (!/#comment$/.test(this.action)) { 12 return; 13 } 11 14 var comment = $('input[@name=replyto]', this)[0]; 12 15 if (comment) { 13 16 comment = comment.value; -
ticketdelete/templates/ticketdelete_admin.html
old new 1 <div xmlns="http://www.w3.org/1999/xhtml" 2 xmlns:py="http://genshi.edgewall.org/" 3 id="page"> 4 <h2>Delete Ticket<py:if ticketdelete.page="comments"> Changes</py:if></h2> 1 <!DOCTYPE html 2 PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" 3 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 4 <html xmlns="http://www.w3.org/1999/xhtml" 5 xmlns:xi="http://www.w3.org/2001/XInclude" 6 xmlns:py="http://genshi.edgewall.org/"> 7 <xi:include href="admin.html" /> 8 <head> 9 <title>Delete</title> 10 </head> 11 <body> 5 12 13 <h2>Delete Ticket<py:if test="ticketdelete.page == 'comments'"> Changes</py:if></h2> 14 6 15 <py:choose> 7 16 <py:when test="ticketdelete.message and ticketdelete.redir"> 8 17 <b>${ticketdelete.message}</b><br /> … … 22 31 </form> 23 32 </py:when> 24 33 <py:when test="ticketdelete.page == 'comments'"> 25 <py:choose has_tickets="len(ticketdelete.changes)">26 <py:when has_tickets="True">34 <py:choose test="len(ticketdelete.changes)"> 35 <py:when test="True"> 27 36 <py:if test="ticketdelete.message"> 28 37 <p><b>${ticketdelete.message}</b></p> 29 38 </py:if> … … 34 43 <tbody> 35 44 <py:for each="change in ticketdelete.changes"> 36 45 <tr> 37 <td><input type="checkbox" name="dontcare" value="dontcare" id="checkbox_${change}" checked="${change.checked or None}" /></td>46 <td><input type="checkbox" name="dontcare" value="dontcare" id="checkbox_${change}" checked="${change.checked or None}" onchange="syncchecks(this)" /></td> 38 47 <td colspan="3"><b>Change at ${change.prettytime} by ${change.author}</b></td> 39 48 <td><input type="submit" name="delete_${change}" value="Delete change" /></td> 40 49 <tr> 41 50 <py:for each="field in change.fields"> 42 51 <tr> 43 <td><input type="checkbox" id="checkbox${field}_${change}" name="mdelete" value="${field}_${change}" checked="${change.checked or None}" /></td> 52 <td><input type="checkbox" id="checkbox_${change}_${field}" name="mdelete" value="${field}_${change}" checked="${change.checked or None}" onchange="if(this.checked) { $('#checkbox_${change}').checked = 0; }" /></td> 53 44 54 <td>${field}</td> 45 <py:choose test=" name(field)">55 <py:choose test="str(field)"> 46 56 <td py:when="comment" colspan="2">${field.new}</td> 47 57 48 58 <py:otherwise> … … 61 71 62 72 <script type="text/javascript"> 63 73 <!-- 64 function toggleboxen(me, boxen)74 function syncchecks(me) 65 75 { 66 status = document.getElementById("checkbox_" + me).checked; 67 boxen.pop() // Remove the last (blank) entry. 68 for (box in boxen) { 69 //alert("Changing checkbox"+boxen[box]+"_"+me); 70 document.getElementById("checkbox"+boxen[box]+"_"+me).checked = status; 76 var checked = me.checked; 77 var checks = document.getElementsByTagName("input"); 78 var re = new RegExp("^" + me.id + "_"); 79 for (var i = 0, l = checks.length; i < l; i ++) { 80 var check = checks[i]; 81 if (check.type == "checkbox" && re.test(check.id)) { 82 check.checked = checked; 83 } 71 84 } 72 85 } 73 74 <py:for each="change in ticketdelete.changes">75 addEvent(document.getElementById("checkbox_${change}"), "change", function() {76 var boxen = Array(${py:for each="field in change.fields"${field}",</py:for>"");77 toggleboxen("${change}", boxen); //Array(<py:for each="field in change.fields">"${field}",</py:for>));78 });79 <py:for each="field in change.fields">80 addEvent(document.getElementById("checkbox${field}_${change}"),"change", function() {81 if(!document.getElementById("checkbox${field}_${change}").checked) {82 document.getElementById("checkbox${change}").checked = 0;83 }84 });85 </py:for>86 </py:for>87 88 89 86 //--> 90 87 </script> 91 88 … … 104 101 </py:choose> 105 102 </py:when> 106 103 </py:choose> 107 </div> 104 </body> 105 106 </html>
