aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Reyna <David.Reyna@windriver.com>2019-02-03 14:01:38 -0800
committerDavid Reyna <David.Reyna@windriver.com>2019-02-03 14:01:38 -0800
commitf0d554d1232e7c79c8fdf3aac9cdf753f808c91e (patch)
tree66b7cfbe678ea2766e1b9bf1d441ce6d81245135
parenta961d187186e5139558cf691ad5bddfbc069a7e0 (diff)
downloadsrtool-f0d554d1232e7c79c8fdf3aac9cdf753f808c91e.tar.gz
srtool-f0d554d1232e7c79c8fdf3aac9cdf753f808c91e.tar.bz2
srtool-f0d554d1232e7c79c8fdf3aac9cdf753f808c91e.zip
srtool_search: enhance search with OR, Quotes, Exclude
Enhance the search query processing: * By default, space separators are treated as AND * Add the explicit keywords OR and AND Note: these keywords switch the default separator * Allow OR searches in addition to AND searches Note: mixed searches use the SQL precedence rules * Allow a '-' prefix to exclude a string * Allow single and double quotes for exact matches Examples: * abd def (equals: abc AND def) * abc OR def (equals: OR abc def) * abc OR "def ghi" (equals: abc OR 'def ghi') * abc OR def AND -ghi Signed-off-by: David Reyna <David.Reyna@windriver.com>
-rw-r--r--lib/srtgui/static/js/table.js11
-rw-r--r--lib/srtgui/templates/cves-select-toastertable.html1
-rw-r--r--lib/srtgui/templates/toastertable.html2
-rw-r--r--lib/srtgui/widgets.py26
4 files changed, 33 insertions, 7 deletions
diff --git a/lib/srtgui/static/js/table.js b/lib/srtgui/static/js/table.js
index abcb5ca7..fd241aa6 100644
--- a/lib/srtgui/static/js/table.js
+++ b/lib/srtgui/static/js/table.js
@@ -86,7 +86,8 @@ function tableInit(ctx){
$("#no-results-special-"+ctx.tableName).show();
$("#results-found-"+ctx.tableName).hide();
} else {
- $("#new-search-input-"+ctx.tableName).val(tableParams.search);
+ /* $("#new-search-input-"+ctx.tableName).val(tableParams.search); */
+ $("#new-search-input-"+ctx.tableName).val($("#search-input-"+ctx.tableName).val());
$("#no-results-"+ctx.tableName).show();
}
}
@@ -782,6 +783,10 @@ function tableInit(ctx){
loadData(tableParams);
});
+ $("#new-search-submit-"+ctx.tableName).click(function(e){
+ $("#search-input-"+ctx.tableName).val($("#new-search-input-"+ctx.tableName).val());
+ $('#search-submit-'+ctx.tableName).click();
+ });
clearSearchElements.click(function(e){
e.preventDefault();
@@ -798,6 +803,10 @@ function tableInit(ctx){
if (e.which === 13)
$('#search-submit-'+ctx.tableName).click();
});
+ $("#new-search-input-"+ctx.tableName).keyup(function(e){
+ if (e.which === 13)
+ $('#search-submit-'+ctx.tableName).click();
+ });
/* Stop page jumps when clicking on # links */
$('a[href="#"]').click(function(e){
diff --git a/lib/srtgui/templates/cves-select-toastertable.html b/lib/srtgui/templates/cves-select-toastertable.html
index eaf8f4f0..38828359 100644
--- a/lib/srtgui/templates/cves-select-toastertable.html
+++ b/lib/srtgui/templates/cves-select-toastertable.html
@@ -98,7 +98,6 @@
</div>
<div class="column2">
<p><b><label id="priority">Set Priority:</label></b>
-
<div id="priority-list" class="scrolling" style="width: 120px;">
<div class="checkbox"> <label>
<input type="radio" name="priority" value="4" type="checkbox"> High
diff --git a/lib/srtgui/templates/toastertable.html b/lib/srtgui/templates/toastertable.html
index aa148955..6882b394 100644
--- a/lib/srtgui/templates/toastertable.html
+++ b/lib/srtgui/templates/toastertable.html
@@ -38,7 +38,7 @@
<span class="remove-search-btn-{{table_name}} glyphicon glyphicon-remove-circle" tabindex="-1"></a>
</div>
</div>
- <button class="btn btn-default search-submit-{{table_name}}">
+ <button class="btn btn-default" id="new-search-submit-{{table_name}}">
Search
</button>
<button class="btn btn-link show-all-{{table_name}} remove-search-btn-{{table_name}}">
diff --git a/lib/srtgui/widgets.py b/lib/srtgui/widgets.py
index 9415a7a5..751f7f14 100644
--- a/lib/srtgui/widgets.py
+++ b/lib/srtgui/widgets.py
@@ -36,6 +36,7 @@ import types
import json
import collections
import re
+import shlex
from srtgui.tablefilter import TableFilterMap
from urllib.parse import unquote_plus
@@ -254,18 +255,33 @@ class ToasterTable(TemplateView):
raise Exception("Search fields aren't defined in the model %s"
% self.queryset.model)
+ # HACK: Replace in case of manual page refresh submits URI encoded chars
+ search_term = search_term.replace('%20',' ').replace('%22','"').replace('%27','"').replace('+',' ')
search_queries = None
- for st in search_term.split(" "):
+ next_op = 'AND'
+ for st in shlex.split(search_term):
queries = None
+ if 'OR' == st:
+ next_op = 'OR'
+ continue
+ if 'AND' == st:
+ next_op = 'AND'
+ continue
for field in self.queryset.model.search_allowed_fields:
- query = Q(**{field + '__icontains': st})
+ if st.startswith('-'):
+ query = ~Q(**{field + '__icontains': st[1:]})
+ else:
+ query = Q(**{field + '__icontains': st})
if queries:
queries |= query
else:
queries = query
if search_queries:
- search_queries &= queries
+ if 'OR' == next_op:
+ search_queries |= queries
+ else:
+ search_queries &= queries
else:
search_queries = queries
@@ -307,6 +323,8 @@ class ToasterTable(TemplateView):
cache_name = cache_name + str(key) + str(val)
# No special chars allowed in the cache name apart from dash
+ # (but keep quotes as dashes to support search string)
+ cache_name = re.sub(r'["\']', "-", cache_name)
cache_name = re.sub(r'[^A-Za-z0-9-]', "", cache_name)
if nocache:
@@ -378,7 +396,7 @@ class ToasterTable(TemplateView):
'<!--error-->'
else:
- # Traverse to any foriegn key in the field
+ # Traverse to any foreign key in the field
# e.g. recipe__layer_version__name
model_data = None