Ticket #7562: t7562-autoquery_tweaks-r7557.diff
| File t7562-autoquery_tweaks-r7557.diff, 7.0 KB (added by osimons, 3 months ago) |
|---|
-
trac/ticket/templates/ticket.html
diff --git a/trac/ticket/templates/ticket.html b/trac/ticket/templates/ticket.html
a b 137 137 not in ('type', 'owner')]"> 138 138 <tr> 139 139 <th id="h_reporter">Reported by:</th> 140 <td headers="h_reporter" class="searchable">${reporter_link}</td> 140 <td headers="h_reporter" class="searchable"> 141 ${defined('reporter_link') and reporter_link or authorinfo(ticket.reporter)} 142 </td> 141 143 <th id="h_owner">Owned by:</th> 142 <td headers="h_owner">${owner_link} 144 <td headers="h_owner"> 145 ${defined('owner_link') and owner_link or authorinfo(ticket.owner)} 143 146 </td> 144 147 </tr> 145 148 <tr py:for="row in group(fields, 2, lambda f: f.type != 'textarea')" -
trac/ticket/web_ui.py
diff --git a/trac/ticket/web_ui.py b/trac/ticket/web_ui.py
a b 44 44 from trac.util.presentation import separated 45 45 from trac.util.translation import _, tag_, N_, gettext 46 46 from trac.versioncontrol.diff import get_diff_options, diff_blocks 47 from trac.web import IRequestHandler47 from trac.web import parse_query_string, IRequestHandler 48 48 from trac.web.chrome import add_link, add_script, add_stylesheet, \ 49 49 add_warning, add_ctxtnav, prevnext_nav, Chrome, \ 50 50 INavigationContributor, ITemplateProvider … … 124 124 If set to 'default', this is equivalent to 'yes' for new environments 125 125 but keeps the old behavior for upgraded environments (i.e. 'no'). 126 126 (''since 0.11'').""") 127 128 unlinked_fields = ListOption('ticket', 'unlinked_fields', 129 default=['estimatedhours', 'hours', 'totalhours'], 130 doc="fields to exclude from AutoQuery markup") 127 128 ticketlink_query = Option('query', 'ticketlink_query', 129 default='?status=!closed', 130 doc="""The base query to be used when linkifying values of ticket 131 fields. The query is a URL query 132 string starting with `?` as used in `query:` 133 [TracQuery#UsingTracLinks Trac links]. 134 (''since 0.12'')""") 131 135 132 136 # IContentConverter methods 133 137 … … 1064 1068 for key in field_changes: 1065 1069 ticket[key] = field_changes[key]['new'] 1066 1070 1067 def _query_link(self, req, name, value): 1068 """return a link to /query with the appropriate name and value""" 1069 query = req.href('query', **{name:value}) 1070 args = self.env.config.get('query', 'default_anonymous_query') 1071 if args: 1072 query = '%s&%s' % (query, args) 1073 return tag.a(value, href=query) 1071 def _query_link(self, req, name, value, text=None): 1072 """Return a link to /query with the appropriate name and value""" 1073 args = parse_query_string(self.ticketlink_query) 1074 args[name] = value 1075 return tag.a(text or value, href=req.href.query(**args)) 1076 1077 def _query_link_words(self, req, name, value): 1078 """Splits a list of words and makes a query link to each separately""" 1079 if not isinstance(value, basestring): # None or other non-splitable 1080 return value 1081 args = parse_query_string(self.ticketlink_query) 1082 items = [] 1083 for (i, word) in enumerate(re.split(r'(\s*(?:\s|[,;])\s*)', value)): 1084 if i % 2: 1085 items.append(word) 1086 elif word: 1087 word_args = args.copy() 1088 word_args[name] = '~' + word 1089 items.append(tag.a(word, href=req.href.query(**word_args))) 1090 return tag(items) 1074 1091 1075 1092 def _prepare_fields(self, req, ticket): 1076 1093 context = Context.from_request(req, ticket.resource) … … 1079 1096 name = field['name'] 1080 1097 type_ = field['type'] 1081 1098 1082 # enable a link to custom query for the field1083 if name not in self.unlinked_fields:1099 # enable a link to custom query for all choice fields 1100 if type_ not in ['text', 'textarea']: 1084 1101 field['rendered'] = self._query_link(req, name, ticket[name]) 1085 1102 1086 1103 # per field settings … … 1117 1134 milestone = Resource('milestone', ticket[name]) 1118 1135 field['rendered'] = render_resource_link(self.env, context, 1119 1136 milestone, 'compact') 1137 elif name == 'keywords': 1138 field['rendered'] = self._query_link_words( 1139 req, name, ticket[name]) 1120 1140 elif name == 'cc': 1121 1141 emails = Chrome(self.env).format_emails(context, ticket[name]) 1122 field['rendered'] = emails 1142 field['rendered'] = emails == ticket[name] and \ 1143 self._query_link_words(req, name, emails) or emails 1123 1144 if ticket.exists and \ 1124 1145 'TICKET_EDIT_CC' not in req.perm(ticket.resource): 1125 1146 cc = ticket._old.get('cc', ticket['cc']) … … 1148 1169 elif type_ == 'checkbox': 1149 1170 value = ticket.values.get(name) 1150 1171 if value in ('1', '0'): 1151 field['rendered'] = value == '1' and _('yes') or _('no') 1172 field['rendered'] = self._query_link(req, name, value, 1173 value == '1' and _('yes') or _('no')) 1152 1174 1153 1175 # ensure sane defaults 1154 1176 field.setdefault('optional', False) … … 1270 1292 ticket.values.update(values) 1271 1293 1272 1294 context = Context.from_request(req, ticket.resource) 1295 1296 # Display the owner and reporter links when not obfuscated 1297 chrome = Chrome(self.env) 1298 for user in 'reporter', 'owner': 1299 if chrome.format_author(req, ticket[user]) == ticket[user]: 1300 data['%s_link' % user] = self._query_link(req, user, 1301 ticket[user]) 1302 1273 1303 data.update({ 1274 1304 'context': context, 1275 1305 'fields': fields, 'changes': changes, … … 1278 1308 'action_controls': action_controls, 1279 1309 'action': selected_action, 1280 1310 'change_preview': change_preview, 1281 'reporter_link': self._query_link(req, 'reporter', ticket['reporter']),1282 'owner_link': self._query_link(req, 'owner', ticket['owner'])1283 1311 }) 1284 1312 1285 1313 def rendered_changelog_entries(self, req, ticket, when=None): -
trac/web/api.py
diff --git a/trac/web/api.py b/trac/web/api.py
a b 103 103 def parse_query_string(query_string): 104 104 """Parse a query string into a _RequestArgs.""" 105 105 args = _RequestArgs() 106 if query_string.startswith('?'): 107 query_string = query_string.replace('?', '', 1) 108 if not query_string: 109 return args 106 110 for arg in query_string.split('&'): 107 111 nv = arg.split('=', 1) 108 112 if len(nv) == 2:
