Merge pull request #784 from taigaio/search-into-tags
Search into tags on searches and filtersremotes/origin/issue/4795/notification_even_they_are_disabled
commit
750158a16b
|
@ -20,10 +20,7 @@ answer newbie questions, and generally made taiga that much better:
|
||||||
- Andrea Stagi <stagi.andrea@gmail.com>
|
- Andrea Stagi <stagi.andrea@gmail.com>
|
||||||
- Andrés Moya <andres.moya@kaleidos.net>
|
- Andrés Moya <andres.moya@kaleidos.net>
|
||||||
- Andrey Alekseenko <al42and@gmail.com>
|
- Andrey Alekseenko <al42and@gmail.com>
|
||||||
<<<<<<< HEAD
|
|
||||||
=======
|
|
||||||
- Brett Profitt <brett.profitt@gmail.com>
|
- Brett Profitt <brett.profitt@gmail.com>
|
||||||
>>>>>>> master
|
|
||||||
- Bruno Clermont <bruno@robotinfra.com>
|
- Bruno Clermont <bruno@robotinfra.com>
|
||||||
- Chris Wilson <chris.wilson@aridhia.com>
|
- Chris Wilson <chris.wilson@aridhia.com>
|
||||||
- David Burke <david@burkesoftware.com>
|
- David Burke <david@burkesoftware.com>
|
||||||
|
@ -33,6 +30,7 @@ answer newbie questions, and generally made taiga that much better:
|
||||||
- Julien Palard
|
- Julien Palard
|
||||||
- luyikei <luyikei.qmltu@gmail.com>
|
- luyikei <luyikei.qmltu@gmail.com>
|
||||||
- Motius GmbH <mail@motius.de>
|
- Motius GmbH <mail@motius.de>
|
||||||
|
- Riccardo Coccioli <riccardo.coccioli@immobiliare.it>
|
||||||
- Ricky Posner <e@eposner.com>
|
- Ricky Posner <e@eposner.com>
|
||||||
- Yamila Moreno <yamila.moreno@kaleidos.net>
|
- Yamila Moreno <yamila.moreno@kaleidos.net>
|
||||||
- Yaser Alraddadi <yaser@yr.sa>
|
- Yaser Alraddadi <yaser@yr.sa>
|
||||||
|
|
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -8,6 +8,8 @@
|
||||||
- ProjectTemplates now are sorted by the attribute 'order'.
|
- ProjectTemplates now are sorted by the attribute 'order'.
|
||||||
- Create enpty wiki pages (if not exist) when a new link is created.
|
- Create enpty wiki pages (if not exist) when a new link is created.
|
||||||
- Diff messages in history entries now show only the relevant changes (with some context).
|
- Diff messages in history entries now show only the relevant changes (with some context).
|
||||||
|
- Include created, modified and finished dates for tasks in CSV reports
|
||||||
|
- User stories and tasks listing API call support extra params to include more data (tasks and attachemnts and attachments, respectively)
|
||||||
- Comments:
|
- Comments:
|
||||||
- Now comment owners and project admins can edit existing comments with the history Entry endpoint.
|
- Now comment owners and project admins can edit existing comments with the history Entry endpoint.
|
||||||
- Add a new permissions to allow add comments instead of use the existent modify permission for this purpose.
|
- Add a new permissions to allow add comments instead of use the existent modify permission for this purpose.
|
||||||
|
@ -15,10 +17,9 @@
|
||||||
- New API endpoints over projects to create, rename, edit, delete and mix tags.
|
- New API endpoints over projects to create, rename, edit, delete and mix tags.
|
||||||
- Tag color assignation is not automatic.
|
- Tag color assignation is not automatic.
|
||||||
- Select a color (or not) to a tag when add it to stories, issues and tasks.
|
- Select a color (or not) to a tag when add it to stories, issues and tasks.
|
||||||
- Now comment owners and project admins can edit existing comments with the history Entry endpoint.
|
- Improve search system over stories, tasks and issues:
|
||||||
- Add a new permissions to allow add comments instead of use the existent modify permission for this purpose.
|
- Search into tags too. (thanks to [Riccardo Cocciol](https://github.com/volans-))
|
||||||
- Include created, modified and finished dates for tasks in CSV reports
|
- Weights are applied: (subject = ref > tags > description).
|
||||||
- User stories and tasks listing API call support extra params to include more data (tasks and attachemnts and attachments, respectively)
|
|
||||||
- Import/Export:
|
- Import/Export:
|
||||||
- Gzip export/import support.
|
- Gzip export/import support.
|
||||||
- Export performance improvements.
|
- Export performance improvements.
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
## 2.1.0 Ursus Americanus (2016-05-03)
|
## 2.1.0 Ursus Americanus (2016-05-03)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
- Add sprint name and slug on search results for user stories ((thanks to [@everblut](https://github.com/everblut)))
|
- Add sprint name and slug on search results for user stories (thanks to [@everblut](https://github.com/everblut))
|
||||||
- [API] projects resource: Random order if `discover_mode=true` and `is_featured=true`.
|
- [API] projects resource: Random order if `discover_mode=true` and `is_featured=true`.
|
||||||
- Webhooks: Improve webhook data:
|
- Webhooks: Improve webhook data:
|
||||||
- add permalinks
|
- add permalinks
|
||||||
|
|
|
@ -459,6 +459,7 @@ class QFilter(FilterBackend):
|
||||||
where_clause = ("""
|
where_clause = ("""
|
||||||
to_tsvector('english_nostop',
|
to_tsvector('english_nostop',
|
||||||
coalesce({table}.subject, '') || ' ' ||
|
coalesce({table}.subject, '') || ' ' ||
|
||||||
|
coalesce(array_to_string({table}.tags, ' '), '') || ' ' ||
|
||||||
coalesce({table}.ref) || ' ' ||
|
coalesce({table}.ref) || ' ' ||
|
||||||
coalesce({table}.description, '')) @@ to_tsquery('english_nostop', %s)
|
coalesce({table}.description, '')) @@ to_tsquery('english_nostop', %s)
|
||||||
""".format(table=table))
|
""".format(table=table))
|
||||||
|
|
|
@ -25,55 +25,65 @@ MAX_RESULTS = getattr(settings, "SEARCHES_MAX_RESULTS", 150)
|
||||||
|
|
||||||
|
|
||||||
def search_user_stories(project, text):
|
def search_user_stories(project, text):
|
||||||
model_cls = apps.get_model("userstories", "UserStory")
|
model = apps.get_model("userstories", "UserStory")
|
||||||
where_clause = ("to_tsvector('english_nostop', coalesce(userstories_userstory.subject) || ' ' || "
|
queryset = model.objects.filter(project_id=project.pk)
|
||||||
"coalesce(userstories_userstory.ref) || ' ' || "
|
table = "userstories_userstory"
|
||||||
"coalesce(userstories_userstory.description, '')) "
|
return _search_items(queryset, table, text)
|
||||||
"@@ to_tsquery('english_nostop', %s)")
|
|
||||||
|
|
||||||
queryset = model_cls.objects.filter(project_id=project.pk)
|
|
||||||
|
|
||||||
if text:
|
|
||||||
queryset = queryset.extra(where=[where_clause], params=[to_tsquery(text)])
|
|
||||||
|
|
||||||
queryset = attach_total_points(queryset)
|
|
||||||
return queryset[:MAX_RESULTS]
|
|
||||||
|
|
||||||
|
|
||||||
def search_tasks(project, text):
|
def search_tasks(project, text):
|
||||||
model_cls = apps.get_model("tasks", "Task")
|
model = apps.get_model("userstories", "UserStory")
|
||||||
where_clause = ("to_tsvector('english_nostop', coalesce(tasks_task.subject, '') || ' ' || "
|
queryset = model.objects.filter(project_id=project.pk)
|
||||||
"coalesce(tasks_task.ref) || ' ' || "
|
table = "userstories_userstory"
|
||||||
"coalesce(tasks_task.description, '')) @@ to_tsquery('english_nostop', %s)")
|
return _search_items(queryset, table, text)
|
||||||
|
|
||||||
if text:
|
|
||||||
return (model_cls.objects.extra(where=[where_clause], params=[to_tsquery(text)])
|
|
||||||
.filter(project_id=project.pk)[:MAX_RESULTS])
|
|
||||||
|
|
||||||
return model_cls.objects.filter(project_id=project.pk)[:MAX_RESULTS]
|
|
||||||
|
|
||||||
|
|
||||||
def search_issues(project, text):
|
def search_issues(project, text):
|
||||||
model_cls = apps.get_model("issues", "Issue")
|
model = apps.get_model("userstories", "UserStory")
|
||||||
where_clause = ("to_tsvector('english_nostop', coalesce(issues_issue.subject) || ' ' || "
|
queryset = model.objects.filter(project_id=project.pk)
|
||||||
"coalesce(issues_issue.ref) || ' ' || "
|
table = "userstories_userstory"
|
||||||
"coalesce(issues_issue.description, '')) @@ to_tsquery('english_nostop', %s)")
|
return _search_items(queryset, table, text)
|
||||||
|
|
||||||
if text:
|
|
||||||
return (model_cls.objects.extra(where=[where_clause], params=[to_tsquery(text)])
|
|
||||||
.filter(project_id=project.pk)[:MAX_RESULTS])
|
|
||||||
|
|
||||||
return model_cls.objects.filter(project_id=project.pk)[:MAX_RESULTS]
|
|
||||||
|
|
||||||
|
|
||||||
def search_wiki_pages(project, text):
|
def search_wiki_pages(project, text):
|
||||||
model_cls = apps.get_model("wiki", "WikiPage")
|
model = apps.get_model("wiki", "WikiPage")
|
||||||
where_clause = ("to_tsvector('english_nostop', coalesce(wiki_wikipage.slug) || ' ' || "
|
queryset = model.objects.filter(project_id=project.pk)
|
||||||
"coalesce(wiki_wikipage.content, '')) "
|
tsquery = "to_tsquery('english_nostop', %s)"
|
||||||
"@@ to_tsquery('english_nostop', %s)")
|
tsvector = """
|
||||||
|
setweight(to_tsvector('english_nostop', coalesce(wiki_wikipage.slug)), 'A') ||
|
||||||
|
setweight(to_tsvector('english_nostop', coalesce(wiki_wikipage.content)), 'B')
|
||||||
|
"""
|
||||||
|
|
||||||
|
return _search_by_query(queryset, tsquery, tsvector, text)
|
||||||
|
|
||||||
|
|
||||||
|
def _search_items(queryset, table, text):
|
||||||
|
tsquery = "to_tsquery('english_nostop', %s)"
|
||||||
|
tsvector = """
|
||||||
|
setweight(to_tsvector('english_nostop',
|
||||||
|
coalesce({table}.subject) || ' ' ||
|
||||||
|
coalesce({table}.ref)), 'A') ||
|
||||||
|
setweight(to_tsvector('english_nostop', coalesce(inmutable_array_to_string({table}.tags))), 'B') ||
|
||||||
|
setweight(to_tsvector('english_nostop', coalesce({table}.description)), 'C')
|
||||||
|
""".format(table=table)
|
||||||
|
return _search_by_query(queryset, tsquery, tsvector, text)
|
||||||
|
|
||||||
|
|
||||||
|
def _search_by_query(queryset, tsquery, tsvector, text):
|
||||||
|
select = {
|
||||||
|
"rank": "ts_rank({tsvector},{tsquery})".format(tsquery=tsquery,
|
||||||
|
tsvector=tsvector),
|
||||||
|
}
|
||||||
|
order_by = ["-rank", ]
|
||||||
|
where = ["{tsvector} @@ {tsquery}".format(tsquery=tsquery,
|
||||||
|
tsvector=tsvector), ]
|
||||||
|
|
||||||
if text:
|
if text:
|
||||||
return (model_cls.objects.extra(where=[where_clause], params=[to_tsquery(text)])
|
queryset = queryset.extra(select=select,
|
||||||
.filter(project_id=project.pk)[:MAX_RESULTS])
|
select_params=[to_tsquery(text)],
|
||||||
|
where=where,
|
||||||
|
params=[to_tsquery(text)],
|
||||||
|
order_by=order_by)
|
||||||
|
|
||||||
return model_cls.objects.filter(project_id=project.pk)[:MAX_RESULTS]
|
queryset = attach_total_points(queryset)
|
||||||
|
return queryset[:MAX_RESULTS]
|
||||||
|
|
Loading…
Reference in New Issue