Add support for searching for hashtags

Also for setting hashtags in change lists using the process mark.
Editing hashtags on individual change screens was already supported.
Selecting hashtags on a change screen will now perform a search for
that tag.

Change-Id: Icc23e10bbf22fbe9b1d958758ec6ceb3286e795b
This commit is contained in:
James E. Blair 2021-03-01 14:42:16 -08:00
parent 94310529ed
commit c134a8c6f1
5 changed files with 57 additions and 2 deletions

View File

@ -60,6 +60,10 @@ class SearchCompiler(object):
result = and_(gertty.db.change_table.c.account_key == gertty.db.account_table.c.key,
result)
tables.remove(gertty.db.account_table)
if gertty.db.hashtag_table in tables:
result = and_(gertty.db.hashtag_table.c.change_key == gertty.db.change_table.c.key,
result)
tables.remove(gertty.db.hashtag_table)
if gertty.db.file_table in tables:
# We only want to look at files for the most recent
# revision.

View File

@ -87,6 +87,7 @@ def SearchParser():
| project_key_term
| branch_term
| topic_term
| hashtag_term
| ref_term
| label_term
| message_term
@ -203,6 +204,13 @@ def SearchParser():
p[0] = and_(gertty.db.change_table.c.topic.isnot(None),
gertty.db.change_table.c.topic == p[2])
def p_hashtag_term(p):
'''hashtag_term : OP_HASHTAG string'''
if p[2].startswith('^'):
p[0] = func.matches(p[2], gertty.db.hashtag_table.c.name)
else:
p[0] = gertty.db.hashtag_table.c.name == p[2]
def p_ref_term(p):
'''ref_term : OP_REF string'''
if p[2].startswith('^'):

View File

@ -29,6 +29,7 @@ operators = {
'_project_key': 'OP_PROJECT_KEY', # internal gertty use only
'branch': 'OP_BRANCH',
'topic': 'OP_TOPIC',
'hashtag': 'OP_HASHTAG',
'ref': 'OP_REF',
#'tr': 'OP_TR', # needs trackingids
#'bug': 'OP_BUG', # needs trackingids

View File

@ -595,7 +595,7 @@ class ChangeView(urwid.WidgetWrap):
self.project_label = mywid.TextButton(u'', on_press=self.searchProject)
self.branch_label = urwid.Text(u'', wrap='clip')
self.topic_label = mywid.TextButton(u'', on_press=self.searchTopic)
self.hashtags_label = urwid.Text(u'', wrap='clip')
self.hashtags_label = mywid.HyperText(u'')
self.created_label = urwid.Text(u'', wrap='clip')
self.updated_label = urwid.Text(u'', wrap='clip')
self.status_label = urwid.Text(u'', wrap='clip')
@ -735,7 +735,16 @@ class ChangeView(urwid.WidgetWrap):
self.project_label.text.set_text(('change-data', change.project.name))
self.branch_label.set_text(('change-data', change.branch))
self.topic_label.text.set_text(('change-data', self.topic))
self.hashtags_label.set_text(('change-data', ' '.join([x.name for x in change.hashtags])))
hashtag_buttons = []
for x in change.hashtags:
if hashtag_buttons:
hashtag_buttons.append(' ')
link = mywid.Link(x.name, 'change-data', 'focused-change-data')
urwid.connect_signal(
link, 'selected',
lambda link, x=x: self.searchHashtags(x.name))
hashtag_buttons.append(link)
self.hashtags_label.set_text(('change-data', hashtag_buttons or u''))
self.created_label.set_text(('change-data', str(self.app.time(change.created))))
self.updated_label.set_text(('change-data', str(self.app.time(change.updated))))
stat = change.wip and 'WIP' or change.status
@ -1300,6 +1309,9 @@ class ChangeView(urwid.WidgetWrap):
if self.topic:
self.app.doSearch("status:open topic:%s" % (self.topic,))
def searchHashtags(self, name):
self.app.doSearch("status:open hashtag:%s" % (name,))
def reviewKey(self, reviewkey):
approvals = {}
for a in reviewkey['approvals']:

View File

@ -362,6 +362,8 @@ class ChangeListView(urwid.WidgetWrap, mywid.Searchable):
"Abandon the marked changes"),
(keymap.EDIT_TOPIC,
"Set the topic of the marked changes"),
(keymap.EDIT_HASHTAGS,
"Edit the hashtags of this change"),
(keymap.RESTORE_CHANGE,
"Restore the marked changes"),
(keymap.REFRESH,
@ -755,6 +757,9 @@ class ChangeListView(urwid.WidgetWrap, mywid.Searchable):
if keymap.EDIT_TOPIC in commands:
self.editTopic()
return True
if keymap.EDIT_HASHTAGS in commands:
self.editHashtags()
return None
if keymap.REFRESH in commands:
if self.project_key:
self.app.sync.submitTask(
@ -880,6 +885,31 @@ class ChangeListView(urwid.WidgetWrap, mywid.Searchable):
self.app.backScreen()
self.refresh()
def editHashtags(self):
dialog = view_change.EditHashtagsDialog(self.app, '')
urwid.connect_signal(dialog, 'save',
lambda button: self.closeEditHashtags(dialog, True))
urwid.connect_signal(dialog, 'cancel',
lambda button: self.closeEditHashtags(dialog, False))
self.app.popup(dialog)
def closeEditHashtags(self, dialog, save):
if save:
rows = [row for row in self.change_rows.values() if row.mark]
if not rows:
pos = self.listbox.focus_position
rows = [self.listbox.body[pos]]
change_keys = [row.change_key for row in rows]
with self.app.db.getSession() as session:
for change_key in change_keys:
change = session.getChange(change_key)
change.setHashtags([x.strip() for x in dialog.entry.edit_text.split(',')])
change.pending_hashtags = True
self.app.sync.submitTask(
sync.SetHashtagsTask(change_key, sync.HIGH_PRIORITY))
self.app.backScreen()
self.refresh()
def abandonChange(self):
dialog = mywid.TextEditDialog(u'Abandon Change', u'Abandon message:',
u'Abandon Change', u'')