Commit fa241542 authored by Michal Čihař's avatar Michal Čihař

Rewritten search for better performance and user experience.

Search is no longer performed on each request, but rather once and then
results are cached.

- correct message for no search results (issue #219)
- allows to go back in translated strings (issue #229)
parent 8a3fb733
......@@ -18,6 +18,7 @@ Released on ? 2013.
* Various performance improvements.
* Indicate failing checks or fuzzy strings in progress bars for projects or languages as well.
* Added support for custom pre-commit hooks and commiting additional files.
* Rewritten search for better performance and user experience.
weblate 1.4
-----------
......
This diff is collapsed.
......@@ -97,87 +97,6 @@ def get_project_translation(request, project=None, subproject=None, lang=None):
return project, subproject, translation
def bool2str(val):
'''
Returns string to use in URL for boolean value.
'''
if val:
return 'on'
return ''
class SearchOptions(object):
'''
Wrapper to search options supplied by user.
'''
def __init__(self, request):
'''
Parses request and fills in search options.
'''
# Default values
self.query = ''
self.type = 'ftx'
self.source = True
self.target = True
self.context = False
self.url = ''
# Search type
self.rqtype = request.REQUEST.get('type', 'all')
# Browsing direction
self.direction = request.REQUEST.get('dir', 'forward')
# Current position
pos = request.REQUEST.get('pos', '-1')
try:
self.pos = int(pos)
except:
self.pos = -1
# Process search form
if request.method == 'POST':
search_form = SearchForm(request.POST)
else:
search_form = SearchForm(request.GET)
if search_form.is_valid():
self.load_form(search_form)
# Include date for review search
if 'date' in request.REQUEST:
self.url += '&date=%s' % request.REQUEST['date']
def load_form(self, search_form):
'''
Loads data from (valid) search form.
'''
# Search query
self.query = search_form.cleaned_data['q']
# Search type
self.type = search_form.cleaned_data['search']
if self.type == '':
self.type = 'ftx'
# Search options
self.source = search_form.cleaned_data['src']
self.target = search_form.cleaned_data['tgt']
self.context = search_form.cleaned_data['ctx']
# Sane defaults
if not self.context and not self.source and not self.target:
self.source = True
self.target = True
# Generate URL
self.url = '&q=%s&src=%s&tgt=%s&ctx=%s&search=%s' % (
self.query,
bool2str(self.source),
bool2str(self.target),
bool2str(self.context),
self.type,
)
def get_filter_name(rqtype, search_query):
'''
Returns name of current filter.
......
......@@ -28,7 +28,6 @@ from django.db.models import Q
from trans.models import Unit, Check, Dictionary
from trans.machine import MACHINE_TRANSLATION_SERVICES
from trans.views.helper import SearchOptions
from trans.decorators import any_permission_required
from trans.views.helper import get_project, get_subproject, get_translation
import weblate
......@@ -109,13 +108,11 @@ def get_other(request, unit_id):
other = Unit.objects.same(unit)
search_options = SearchOptions(request)
return render_to_response('js/other.html', RequestContext(request, {
'other': other,
'unit': unit,
'type': search_options.rqtype,
'search_url': search_options.url,
'search_id': request.GET.get('sid', ''),
'offset': request.GET.get('offset', ''),
}))
......
......@@ -14,7 +14,7 @@
<td>{% include "unit-state.html" %}</td>
<td>
{% if perms.trans.save_translation %}
<a class="mergebutton small-button" href="{{ unit.translation.get_translate_url}}?type={{ type }}&amp;pos={{ unit.position }}{{ search_url }}&amp;checksum={{ unit.checksum }}&amp;merge={{ item.id }}" title="{% trans "Use this translation for all subprojects" %}">{% trans "Use this translation" %}</a>
<a class="mergebutton small-button" href="{{ unit.translation.get_translate_url}}?sid={{ search_id }}&amp;offset={{ offset }}&amp;checksum={{ unit.checksum }}&amp;merge={{ item.id }}" title="{% trans "Use this translation for all subprojects" %}">{% trans "Use this translation" %}</a>
{% endif %}
</td>
</tr>
......
......@@ -25,11 +25,11 @@
<span class="navi-toolbar ui-widget-header ui-corner-all">
<span id="navi">
<a id="button-first" href="{{ unit.translation.get_translate_url }}?type={{ type }}&amp;pos=1&amp;dir=stay{{ search_url }}">{% trans "First" %}</a>
<a id="button-prev" href="{{ unit.translation.get_translate_url }}?type={{ type }}&amp;pos={{ unit.position }}&amp;dir=back{{ search_url }}">{% trans "Previous" %}</a>
<a id="button-first" href="{{ first_unit_url }}">{% trans "First" %}</a>
<a id="button-prev" href="{{ prev_unit_url }}">{% trans "Previous" %}</a>
<a id="button-pos" class="textbutton">{% blocktrans with unit.position as position %}{{ position }} / {{ total }}{% endblocktrans %}</a>
<a id="button-next" href="{{ unit.translation.get_translate_url }}?type={{ type }}&amp;pos={{ unit.position }}{{ search_url }}">{% trans "Next" %}</a>
<a id="button-end" href="{{ unit.translation.get_translate_url }}?type={{ type }}&amp;pos={{ total }}&amp;dir=stay{{ search_url }}">{% trans "Last" %}</a>
<a id="button-next" href="{{ next_unit_url }}">{% trans "Next" %}</a>
<a id="button-end" href="{{ last_unit_url }}">{% trans "Last" %}</a>
</span>
{% if filter_name %}
......@@ -37,18 +37,11 @@
{% endif %}
</span>
<form action="{{ unit.translation.get_translate_url }}" method="post">
<form action="{{ this_unit_url }}" method="post">
<a href="{% url 'js-get' checksum=unit.checksum %}" class="hidden" id="js-get"></a>
<a href="{% url 'js-lock' project=unit.translation.subproject.project.slug subproject=unit.translation.subproject.slug lang=unit.translation.language.code %}" class="hidden" id="js-lock"></a>
{% csrf_token %}
{% if antispam %}<div id="s_content">{{ antispam }}</div>{% endif %}
<input type="hidden" name="type" value="{{ type }}" />
<input type="hidden" name="pos" value="{{ unit.position }}" />
<input type="hidden" name="q" value="{{ search_query }}" />
<input type="hidden" name="search" value="{{ search_type }}" />
<input type="hidden" name="src" value="{{ search_source }}" />
<input type="hidden" name="tgt" value="{{ search_target }}" />
<input type="hidden" name="ctx" value="{{ search_context }}" />
<table>
{% if secondary %}
{% for unit in secondary %}
......@@ -127,10 +120,10 @@
{% if perms.trans.accept_suggestion or perms.trans.delete_suggestion %}
<div class="menu-float action-buttons">
{% if perms.trans.accept_suggestion %}
<a href="{{ suggestion.get_translate_url }}?type={{ type }}&amp;pos={{ unit.position }}&amp;accept={{ suggestion.id }}{{ search_url }}" class="sug-accept">{% trans "Accept" %}</a>
<a href="{{ this_unit_url }}&amp;accept={{ suggestion.id }}" class="sug-accept">{% trans "Accept" %}</a>
{% endif %}
{% if perms.trans.delete_suggestion %}
<a href="{{ suggestion.get_translate_url }}?type={{ type }}&amp;pos={{ unit.position }}&amp;delete={{ suggestion.id }}{{ search_url }}" class="sug-delete">{% trans "Delete" %}</a>
<a href="{{ this_unit_url }}&amp;delete={{ suggestion.id }}" class="sug-delete">{% trans "Delete" %}</a>
{% endif %}
</div>
{% endif %}
......@@ -169,7 +162,7 @@
<ul>
<li><a href="#tab-nearby" title="{% trans "Messages placed around this one" %}">{% trans "Nearby messages" %}</a></li>
<li><a href="{% url 'js-similar' unit_id=unit.id %}" title="{% trans "Similar messages" %}">{% trans "Similar messages" %}</a></li>
<li><a href="{% url 'js-other' unit_id=unit.id %}?type={{ type }}&amp;pos={{ unit.position }}{{ search_url }}" title="{% trans "Same message used in different subprojects" %}">{% trans "All locations" %}</a></li>
<li><a href="{% url 'js-other' unit_id=unit.id %}?type={{ type }}&amp;offset={{ offset }}&amp;sid={{ search_id }}" title="{% trans "Same message used in different subprojects" %}">{% trans "All locations" %}</a></li>
<li><a href="{% url 'js-dictionary' unit_id=unit.id %}" title="{% trans "Words extracted from glossary" %}">{% trans "Glossary" %}</a></li>
<li><a href="#tab-comments" title="{% trans "Comments about this translation" %}">{% trans "Comments" %}</a></li>
<li><a href="#tab-changes" title="{% trans "List of recent changes done in Weblate" %}">{% trans "Recent edits" %}</a></li>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment