--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -306,6 +306,33 @@
def bins(self):
return TM.Bin.query.find(dict(app_config_id=self.config._id)).sort('summary').all()
+
+
+
+
+### Controllers ###
+
+def mongo_columns():
+ columns = [dict(name='ticket_num', sort_name='ticket_num', label='Ticket Number', active=True),
+ dict(name='summary', sort_name='summary', label='Summary', active=True),
+ dict(name='_milestone', sort_name='custom_fields._milestone', label='Milestone', active=True),
+ dict(name='status', sort_name='status', label='Status', active=True),
+ dict(name='assigned_to', sort_name='assigned_to_username', label='Owner', active=True)]
+ for field in c.app.globals.sortable_custom_fields_shown_in_search():
+ columns.append(
+ dict(name=field['name'], sort_name=field['name'], label=field['label'], active=True))
+ return columns
+
+def solr_columns():
+ columns = [dict(name='ticket_num', sort_name='ticket_num_i', label='Ticket Number', active=True),
+ dict(name='summary', sort_name='snippet_s', label='Summary', active=True),
+ dict(name='_milestone', sort_name='_milestone_s', label='Milestone', active=True),
+ dict(name='status', sort_name='status_s', label='Status', active=True),
+ dict(name='assigned_to', sort_name='assigned_to_s', label='Owner', active=True)]
+ for field in c.app.globals.sortable_custom_fields_shown_in_search():
+ columns.append(dict(name=field['name'], sort_name=field['sortable_name'], label=field['label'], active=True))
+ return columns
+
class RootController(BaseController):
def __init__(self):
@@ -331,84 +358,17 @@
bin_counts.append(dict(label=label, count=count))
return dict(bin_counts=bin_counts)
- def paged_query(self, q, limit=None, page=0, sort=None, columns=None, **kw):
- """Query tickets, sorting and paginating the result.
-
- We do the sorting and skipping right in SOLR, before we ever ask
- Mongo for the actual tickets. Other keywords for
- search_artifact (e.g., history) or for SOLR are accepted through
- kw. The output is intended to be used directly in templates,
- e.g., exposed controller methods can just:
-
- return paged_query(q, ...)
-
- If you want all the results at once instead of paged you have
- these options:
- - don't call this routine, search directly in mongo
- - call this routine with a very high limit and TEST that
- count<=limit in the result
- limit=-1 is NOT recognized as 'all'. 500 is a reasonable limit.
- """
-
- limit, page, start = g.handle_paging(limit, page, default=25)
- count = 0
- tickets = []
- refined_sort = sort if sort else 'ticket_num_i asc'
- if 'ticket_num_i' not in refined_sort:
- refined_sort += ',ticket_num_i asc'
- try:
- if q:
- matches = search_artifact(
- TM.Ticket, q,
- rows=limit, sort=refined_sort, start=start, fl='ticket_num_i', **kw)
- else:
- matches = None
- solr_error = None
- except ValueError, e:
- solr_error = e.args[0]
- matches = []
- if matches:
- count = matches.hits
- # ticket_numbers is in sorted order
- ticket_numbers = [match['ticket_num_i'] for match in matches.docs]
- # but query, unfortunately, returns results in arbitrary order
- query = TM.Ticket.query.find(dict(app_config_id=c.app.config._id, ticket_num={'$in':ticket_numbers}))
- # so stick all the results in a dictionary...
- ticket_for_num = {}
- for t in query:
- ticket_for_num[t.ticket_num] = t
- # and pull them out in the order given by ticket_numbers
- tickets = []
- for tn in ticket_numbers:
- if tn in ticket_for_num:
- if has_access(ticket_for_num[tn], 'read'):
- tickets.append(ticket_for_num[tn])
- else:
- count = count -1
- sortable_custom_fields=c.app.globals.sortable_custom_fields_shown_in_search()
- if not columns:
- columns = [dict(name='ticket_num', sort_name='ticket_num_i', label='Ticket Number', active=True),
- dict(name='summary', sort_name='snippet_s', label='Summary', active=True),
- dict(name='_milestone', sort_name='_milestone_s', label='Milestone', active=True),
- dict(name='status', sort_name='status_s', label='Status', active=True),
- dict(name='assigned_to', sort_name='assigned_to_s', label='Owner', active=True)]
- for field in sortable_custom_fields:
- columns.append(dict(name=field['name'], sort_name=field['sortable_name'], label=field['label'], active=True))
- return dict(tickets=tickets,
- sortable_custom_fields=sortable_custom_fields,
- columns=columns,
- count=count, q=q, limit=limit, page=page, sort=sort,
- solr_error=solr_error, **kw)
-
@with_trailing_slash
@h.vardec
@expose('jinja:forgetracker:templates/tracker/index.html')
def index(self, limit=25, columns=None, page=0, sort='ticket_num desc', **kw):
kw.pop('q', None) # it's just our original query mangled and sent back to us
- result = TM.Ticket.paged_query(c.app.globals.not_closed_mongo_query,
+ result = TM.Ticket.paged_query(c.app.config, c.user,
+ c.app.globals.not_closed_mongo_query,
sort=sort, limit=int(limit),
- columns=columns, page=page, **kw)
- c.subscribe_form = W.subscribe_form
+ page=page, **kw)
+ result['columns'] = columns or mongo_columns()
+ result['sortable_custom_fields'] = c.app.globals.sortable_custom_fields_shown_in_search()
result['subscribed'] = M.Mailbox.subscribed()
result['allow_edit'] = has_access(c.app, 'update')()
result['help_msg'] = c.app.config.options.get('TicketHelpSearch')
@@ -418,6 +378,7 @@
sort_split = sort.split(' ')
solr_col = _mongo_col_to_solr_col(sort_split[0])
result['url_sort'] = '%s %s' % (solr_col, sort_split[1])
+ c.subscribe_form = W.subscribe_form
c.ticket_search_results = W.ticket_search_results
return result
@@ -506,7 +467,9 @@
bin = TM.Bin.query.find(dict(app_config_id=c.app.config._id,terms=q)).first()
if project:
redirect(c.project.url() + 'search?' + urlencode(dict(q=q, history=kw.get('history'))))
- result = self.paged_query(q, page=page, sort=sort, columns=columns, **kw)
+ result = TM.Ticket.paged_search(c.app.config, c.user, q, page=page, sort=sort, **kw)
+ result['columns'] = columns or solr_columns()
+ result['sortable_custom_fields'] = c.app.globals.sortable_custom_fields_shown_in_search()
result['allow_edit'] = has_access(c.app, 'update')()
result['bin'] = bin
result['help_msg'] = c.app.config.options.get('TicketHelpSearch')
@@ -517,23 +480,24 @@
@h.vardec
@expose()
@validate(validators=search_validators)
- def search_feed(self, q=None, query=None, project=None, columns=None, page=0, sort=None, **kw):
+ def search_feed(self, q=None, query=None, project=None, page=0, sort=None, **kw):
if query and not q:
q = query
- result = self.paged_query(q, page=page, sort=sort, columns=columns, **kw)
+ result = TM.Ticket.paged_search(c.app.config, c.user, q, page=page, sort=sort, **kw)
response.headers['Content-Type'] = ''
response.content_type = 'application/xml'
- d = dict(title='Ticket search results', link=c.app.url, description='You searched for %s' % q, language=u'en')
+ d = dict(title='Ticket search results', link=h.absurl(c.app.url), description='You searched for %s' % q, language=u'en')
if request.environ['PATH_INFO'].endswith('.atom'):
feed = FG.Atom1Feed(**d)
else:
feed = FG.Rss201rev2Feed(**d)
for t in result['tickets']:
+ url = h.absurl(t.url().encode('utf-8'))
feed.add_item(title=t.summary,
- link=h.absurl(t.url().encode('utf-8')),
+ link=url,
pubdate=t.mod_date,
description=t.description,
- unique_id=str(t._id),
+ unique_id=url,
author_name=t.reported_by.display_name,
author_link=h.absurl(t.reported_by.url()))
return feed.writeString('utf-8')
@@ -622,9 +586,11 @@
sort=validators.UnicodeString(if_empty='ticket_num_i asc')))
def edit(self, q=None, limit=None, page=None, sort=None, **kw):
require_access(c.app, 'update')
- result = self.paged_query(q, sort=sort, limit=limit, page=page, **kw)
+ result = TM.Ticket.paged_search(c.app.config, c.user, q, sort=sort, limit=limit, page=page, **kw)
# if c.app.globals.milestone_names is None:
# c.app.globals.milestone_names = ''
+ result['columns'] = solr_columns()
+ result['sortable_custom_fields'] = c.app.globals.sortable_custom_fields_shown_in_search()
result['globals'] = c.app.globals
result['cancel_href'] = url(
c.app.url + 'search/',
@@ -1338,10 +1304,14 @@
require_access(c.app, 'read')
@expose('json:')
- def index(self, **kw):
- return dict(tickets=[
- dict(ticket_num=t.ticket_num, summary=t.summary)
- for t in TM.Ticket.query.find(dict(app_config_id=c.app.config._id)).sort('ticket_num') ])
+ def index(self, limit=100, page=0, **kw):
+ results = TM.Ticket.paged_query(c.app.config, c.user, query={},
+ limit=int(limit), page=int(page))
+ results['tickets'] = [dict(ticket_num=t.ticket_num, summary=t.summary)
+ for t in results['tickets']]
+ results.pop('q', None)
+ results.pop('sort', None)
+ return results
@expose()
@h.vardec
@@ -1384,6 +1354,13 @@
except Exception, e:
log.exception(e)
return dict(status=False, errors=[str(e)])
+
+ @expose('json:')
+ def search(self, q=None, limit=100, page=0, sort=None, **kw):
+ results = TM.Ticket.paged_search(c.app.config, c.user, q, limit, page, sort)
+ results['tickets'] = [dict(ticket_num=t.ticket_num, summary=t.summary)
+ for t in results['tickets']]
+ return results
@expose()
def _lookup(self, ticket_num, *remainder):
@@ -1445,8 +1422,10 @@
sort=validators.UnicodeString(if_empty=None)))
def index(self, q=None, columns=None, page=0, query=None, sort=None, **kw):
require(has_access(c.app, 'read'))
- result = TM.Ticket.paged_query(
- self.mongo_query, page=page, sort=sort, columns=columns, **kw)
+ result = TM.Ticket.paged_query(c.app.config, c.user,
+ self.mongo_query, page=page, sort=sort, **kw)
+ result['columns'] = columns or mongo_columns()
+ result['sortable_custom_fields'] = c.app.globals.sortable_custom_fields_shown_in_search()
result['allow_edit'] = has_access(c.app, 'update')()
result['help_msg'] = c.app.config.options.get('TicketHelpSearch')
progress = c.app.globals.milestone_count(self.progress_key)
@@ -1474,8 +1453,10 @@
sort=validators.UnicodeString(if_empty='ticket_num_i asc')))
def edit(self, q=None, limit=None, page=None, sort=None, columns=None, **kw):
require_access(c.app, 'update')
- result = TM.Ticket.paged_query(
- self.mongo_query, page=page, sort=sort, columns=columns, **kw)
+ result = TM.Ticket.paged_query(c.app.config, c.user,
+ self.mongo_query, page=page, sort=sort, **kw)
+ result['columns'] = columns or mongo_columns()
+ result['sortable_custom_fields'] = c.app.globals.sortable_custom_fields_shown_in_search()
# if c.app.globals.milestone_names is None:
# c.app.globals.milestone_names = ''
result.pop('q')