diff --git a/trac/ticket/query.py b/trac/ticket/query.py
|
a
|
b
|
|
| 693 | 693 | doc='The default query for authenticated users.') |
| 694 | 694 | |
| 695 | 695 | default_anonymous_query = Option('query', 'default_anonymous_query', |
| 696 | | default='status!=closed&cc~=$USER', |
| | 696 | default='status=!closed', |
| 697 | 697 | doc='The default query for anonymous users.') |
| 698 | 698 | |
| 699 | 699 | items_per_page = IntOption('query', 'items_per_page', 100, |
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')" |
diff --git a/trac/ticket/web_ui.py b/trac/ticket/web_ui.py
|
a
|
b
|
|
| 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") |
| 131 | 127 | |
| 132 | 128 | # IContentConverter methods |
| 133 | 129 | |
| … |
… |
|
| 1064 | 1060 | for key in field_changes: |
| 1065 | 1061 | ticket[key] = field_changes[key]['new'] |
| 1066 | 1062 | |
| 1067 | | def _query_link(self, req, name, value): |
| 1068 | | """return a link to /query with the appropriate name and value""" |
| | 1063 | def _query_link(self, req, name, value, text=None): |
| | 1064 | """Return a link to /query with the appropriate name and value""" |
| 1069 | 1065 | query = req.href('query', **{name:value}) |
| 1070 | 1066 | args = self.env.config.get('query', 'default_anonymous_query') |
| 1071 | 1067 | if args: |
| 1072 | 1068 | query = '%s&%s' % (query, args) |
| 1073 | | return tag.a(value, href=query) |
| | 1069 | return tag.a(text or value, href=query) |
| | 1070 | |
| | 1071 | def _query_link_words(self, req, name, value): |
| | 1072 | """Splits a list of words and makes a query link to each separately""" |
| | 1073 | if not isinstance(value, basestring): # None or other non-splitable |
| | 1074 | return value |
| | 1075 | default = self.env.config.get('query', 'default_anonymous_query', '') |
| | 1076 | items = [] |
| | 1077 | for word in value.split(): |
| | 1078 | word = word.strip(",.;") |
| | 1079 | if word: |
| | 1080 | link = req.href('query', **{name: '~' + word}) \ |
| | 1081 | + (default and '&' + default or '') |
| | 1082 | items.append((tag.a(word, href=link), ' ')) |
| | 1083 | return tag(items) |
| 1074 | 1084 | |
| 1075 | 1085 | def _prepare_fields(self, req, ticket): |
| 1076 | 1086 | context = Context.from_request(req, ticket.resource) |
| … |
… |
|
| 1079 | 1089 | name = field['name'] |
| 1080 | 1090 | type_ = field['type'] |
| 1081 | 1091 | |
| 1082 | | # enable a link to custom query for the field |
| 1083 | | if name not in self.unlinked_fields: |
| | 1092 | # enable a link to custom query for all choice fields |
| | 1093 | if type_ not in ['text', 'textarea']: |
| 1084 | 1094 | field['rendered'] = self._query_link(req, name, ticket[name]) |
| 1085 | 1095 | |
| 1086 | 1096 | # per field settings |
| … |
… |
|
| 1117 | 1127 | milestone = Resource('milestone', ticket[name]) |
| 1118 | 1128 | field['rendered'] = render_resource_link(self.env, context, |
| 1119 | 1129 | milestone, 'compact') |
| | 1130 | elif name == 'keywords': |
| | 1131 | field['rendered'] = self._query_link_words( |
| | 1132 | req, name, ticket[name]) |
| 1120 | 1133 | elif name == 'cc': |
| 1121 | 1134 | emails = Chrome(self.env).format_emails(context, ticket[name]) |
| 1122 | | field['rendered'] = emails |
| | 1135 | field['rendered'] = emails == ticket[name] and \ |
| | 1136 | self._query_link_words(req, name, emails) or emails |
| 1123 | 1137 | if ticket.exists and \ |
| 1124 | 1138 | 'TICKET_EDIT_CC' not in req.perm(ticket.resource): |
| 1125 | 1139 | cc = ticket._old.get('cc', ticket['cc']) |
| … |
… |
|
| 1148 | 1162 | elif type_ == 'checkbox': |
| 1149 | 1163 | value = ticket.values.get(name) |
| 1150 | 1164 | if value in ('1', '0'): |
| 1151 | | field['rendered'] = value == '1' and _('yes') or _('no') |
| | 1165 | field['rendered'] = self._query_link(req, name, value, |
| | 1166 | value == '1' and _('yes') or _('no')) |
| 1152 | 1167 | |
| 1153 | 1168 | # ensure sane defaults |
| 1154 | 1169 | field.setdefault('optional', False) |
| … |
… |
|
| 1270 | 1285 | ticket.values.update(values) |
| 1271 | 1286 | |
| 1272 | 1287 | context = Context.from_request(req, ticket.resource) |
| | 1288 | |
| | 1289 | # Display the owner and reporter links when not obfuscated |
| | 1290 | chrome = Chrome(self.env) |
| | 1291 | for user in 'reporter', 'owner': |
| | 1292 | if chrome.format_author(req, ticket[user]) == ticket[user]: |
| | 1293 | data['%s_link' % user] = self._query_link(req, user, |
| | 1294 | ticket[user]) |
| | 1295 | |
| 1273 | 1296 | data.update({ |
| 1274 | 1297 | 'context': context, |
| 1275 | 1298 | 'fields': fields, 'changes': changes, |
| … |
… |
|
| 1278 | 1301 | 'action_controls': action_controls, |
| 1279 | 1302 | 'action': selected_action, |
| 1280 | 1303 | '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 | 1304 | }) |
| 1284 | 1305 | |
| 1285 | 1306 | def rendered_changelog_entries(self, req, ticket, when=None): |