Skip to content

Commit

Permalink
Search: inline editing and ordering (#3766)
Browse files Browse the repository at this point in the history
* Query Field: Separates query field from the pagination part

Separates the query search field from the pagination part and adds filters
and sorting options in UI

* Query Field: Adds sorting feature from the query field dropdown

* Refactors code for sorting and filtering

* Autosort and auto filter queries on selecting dropdown

* Adds selenium tests and more sort options

* Adds fixes for some accessibility issues related to input

* Refactor codes to make more readable

* Fix selenium tests

- add delay before screenshots to avoid capturing transitions
- revert to original search for other tests

* Adds sorting direction feature with suitable icons

* Shows dropdown labels and enables autosearch in page with results

* Use bootstrap button group for sorting

* Use default autosizing width of button for sort dropdown

* Fixes button display in RTL

* Adds sort_by to SearchForm along with the direction

* Uses a separate class to identify autosubmit

* Adds query search field in zen pages

* Adds check to see if the current page has a sort field and a sort value set

Issue  #3308, #3710

Co-authored-by: Michal Čihař <[email protected]>
  • Loading branch information
SaptakS and nijel authored May 6, 2020
1 parent ee66e46 commit da0b288
Show file tree
Hide file tree
Showing 18 changed files with 347 additions and 85 deletions.
1 change: 1 addition & 0 deletions weblate/static/icons/sort-ascending.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions weblate/static/icons/sort-descending.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
61 changes: 58 additions & 3 deletions weblate/static/loader-bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,27 @@ $(function () {
$(this).parent().find('input').attr('disabled', '1');
});

// Show the correct toggle button
if ($('.sort-field').length) {
var sort_name = $('#query-sort-dropdown span.search-label').text();
var sort_dropdown_value = $(".sort-field li a").filter(function() {
return $(this).text() == sort_name;
}).data('sort');
var sort_value = $('#id_sort_by').val();
if (sort_dropdown_value) {
if (
sort_value.replace("-", "") === sort_dropdown_value.replace("-", "")
&& sort_value !== sort_dropdown_value
) {
$('#query-sort-toggle .asc').hide();
$('#query-sort-toggle .desc').show();
} else {
$('#query-sort-toggle .desc').hide();
$('#query-sort-toggle .asc').show();
}
}
}

/* Branch loading */
$('.branch-loader select[name=component]').change(function () {
var $this = $(this);
Expand All @@ -1525,16 +1546,50 @@ $(function () {
$('.search-group li a').click(function () {
var $this = $(this);
var $button = $this.closest('.input-group-btn').find('button');
$button.data('field', $this.data('field'));
$button.find('span.search-label').text($this.text());
$button.attr('data-field', $this.data('field'));
$button.find('span.search-label').not('#query-sort-toggle span').text($this.text());
if ($this.data('sort')) {
$('#id_sort_by').val($this.data('sort'));
if ($this.closest('.result-page-form').length) {
$this.closest('form').submit();
}
}
if ($this.closest('.query-field').length) {
$('#id_q').val($this.data('field'));
if ($this.closest('.result-page-form').length) {
$this.closest('form').submit();
}
}
});
$('.search-group input').on('keydown', function (event) {
$('#query-sort-toggle').click(function () {
var $this = $(this);
var $label = $this.find('span.search-label');
$label.toggle();
var sort_params = $('#id_sort_by').val().split(",")
sort_params.forEach(function(param, index) {
if (param.indexOf("-") !== -1) {
sort_params[index] = param.replace("-", "");
} else {
sort_params[index] = `-${param}`;
}
});
$('#id_sort_by').val(sort_params.join(","));
if ($this.closest('.result-page-form').length) {
$this.closest('form').submit();
}
});
$('.search-group input').not('#id_q').on('keydown', function (event) {
if (event.key === "Enter") {
$(this).closest('.input-group').find('.search-add').click();
event.preventDefault();
return false;
}
});
$('#id_q').on('keydown', function (event) {
if (event.key === "Enter") {
$(this).closest('form').submit();
}
});
$('.search-add').click(function () {
var group = $(this).closest('.input-group');
var button = group.find('button');
Expand Down
50 changes: 49 additions & 1 deletion weblate/static/style-bootstrap.css
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,7 @@ kbd {
text-align: center;
}
.unit-navi {
min-width: 25em;
min-width: 17em;
}
.unit-navi li {
float: left;
Expand All @@ -429,6 +429,10 @@ kbd {
.unit-navi .dropdown-menu {
margin-top: 0;
}
.unit-navi.pagination {
margin-top: 0;
padding-left: 15px;
}
.fullmodal .modal-dialog {
width: auto;
}
Expand All @@ -447,12 +451,52 @@ legend {
.search-group {
margin: 0 15px 15px 0;
}
.query-field {
margin: 0;
}
.search-group input{
height: auto;
}
.search-group li a {
cursor: pointer;
}
.search-label svg {
height: 16px;
}
.query-field .btn.btn-primary{
font-size: initial;
}
.sort-field {
margin: 0;
}
#query-sort-toggle {
padding-left: 1rem;
padding-right: 1rem;
}
#query-sort-toggle span:not(.active) {
display: none;
}
#is-exact span {
margin: 4px 4px 0 4px;
}
.dir-rtl .search-group {
margin: 0 0 15px 15px;
}

.dir-rtl .sort-field {
margin-left: 0;
}
@media (min-width: 768px) {
.sort-field {
margin-left: -15px;
}
.dir-rtl .sort-field {
margin-right: -15px;
}
.query-container {
max-width: calc(100% - 100px);
}
}
.search-toolbar {
margin-bottom: -15px;
}
Expand Down Expand Up @@ -973,6 +1017,10 @@ a.format-item:hover {
display: none;
width: 0;
}

.query-field .input-group {
width: 100%;
}
}
@media (max-width: 900px) {
.zero-width-900 {
Expand Down
2 changes: 1 addition & 1 deletion weblate/templates/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
{% endif %}
{% endif %}

<form method="GET">
<form method="GET" class="result-page-form">
{% include "snippets/search-form.html" %}
</form>

Expand Down
3 changes: 3 additions & 0 deletions weblate/templates/snippets/query-builder.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
{% load i18n %}

{% if show_builder %}
<div class="form-group">
<label class="control-label">{% trans "Advanced query builder" %}</label>

Expand Down Expand Up @@ -104,3 +106,4 @@
</tr>
</table>
</div>
{% endif %}
64 changes: 64 additions & 0 deletions weblate/templates/snippets/query-field.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{% load i18n %}
{% load translations %}
{% load icons %}
{% load crispy_forms_field %}
<div class="row">
<div class="col-sm-9">
<div class="form-group">
<div class="search-group query-field" role="group" >
<div class="input-group">
<div class="input-group-btn">
<button type="button" id="query-dropdown" class="btn btn-default dropdown-toggle search-field" data-field="" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{% if filter_name and filter_name != search_query.strip %}
<span class="search-label">{{ filter_name }}</span>
{% else %}
<span class="search-label">{% trans "Custom Search" %}</span>
{% endif %}
<span class="caret"></span>
</button>
<ul class="dropdown-menu">
{% for _, name, query in custom_filter_list %}
<li><a data-field="{{ query }}">{{ name }}</a></li>
{% endfor %}
</ul>
</div><!-- /btn-group -->
{% crispy_field field 'class' 'form-control' 'aria-label' _('Query') %}
</div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="form-group">
<div class="btn-group search-group sort-field" role="group">
<div class="input-group">
<div class="input-group-btn">
<button type="button" id="query-sort-dropdown" class="btn btn-default dropdown-toggle search-field" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{% if sort_name %}
<span class="search-label">{{ sort_name }}</span>
{% else %}
<span class="search-label">{% trans "Sort By" %}</span>
{% endif %}
<span class="caret"></span>
</button>
<input type="hidden" id="id_sort_by" name="sort_by" value="{{ sort_query|default:'-priority,position' }}" aria-label="{% trans "Sort By" %}" />
<ul class="dropdown-menu">
<li><a data-sort="-priority,position">{% trans "Position and priority" %}</a></li>
<li><a data-sort="position">{% trans "Position" %}</a></li>
<li><a data-sort="priority">{% trans "Priority" %}</a></li>
<li><a data-sort="num_words">{% trans "Word count" %}</a></li>
<li><a data-sort="context">{% trans "Context" %}</a></li>
</ul>
</div>
<span class="input-group-btn">
<button type="button" id="query-sort-toggle" class="btn btn-default search-field">
<span class="search-label asc active">
{% icon "sort-ascending.svg" %}
</span>
<span class="search-label desc">{% icon "sort-descending.svg" %}</span>
</button>
</span>
</div><!-- /input-group -->
</div>
</div>
</div>
</div>
3 changes: 0 additions & 3 deletions weblate/templates/snippets/search-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,4 @@
<div class="panel-body">
{% crispy search_form %}
</div>
<div class="panel-footer">
<input type="submit" value="{% trans "Search" %}" class="btn btn-primary" />
</div>
</div>
95 changes: 46 additions & 49 deletions weblate/templates/translate.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,55 +45,52 @@

{% with comments=unit.get_comments nearby=unit.nearby nearby_keys=unit.nearby_keys shapings=unit.shapings%}

<div class="btn-group">
<ul class="pagination unit-navi">
<li><a id="button-first" class="green" href="{{ first_unit_url }}" title="{% trans "First" %}">{% if LANGUAGE_BIDI %}{% icon "page-last.svg" %}{% else %}{% icon "page-first.svg" %}{% endif %}</a></li>
<li><a id="button-prev" class="green" href="{{ prev_unit_url }}" title="{% trans "Previous" %}">{% if LANGUAGE_BIDI %}{% icon "page-next.svg" %}{% else %}{% icon "page-previous.svg" %}{% endif %}</a></li>
<li class="dropdown">
<a class="dropdown-toggle green" data-toggle="dropdown" href="#" title="{% trans "Edit search parameters" %}" id="search-dropdown">
{% icon "magnify.svg" %}
{{ filter_name }}
<span class="caret"></span>
</a>
<div class="dropdown-menu">

<div class="panel-group">
<form action="{{ unit.translation.get_translate_url }}" method="GET">
{{ search_form|crispy }}
<input type="submit" value="{% trans "Search" %}" class="btn btn-primary" />
</form>
</div>

</div>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" title="{% trans "Go to position" %}" id="goto-dropdown">
{% blocktrans %}{{ filter_pos }} / {{ filter_count }}{% endblocktrans %}
<span class="caret"></span>
</a>
<div class="dropdown-menu">

<div class="panel-group">

<form action="{{ unit.translation.get_translate_url }}" method="GET">
{% for key, value in search_items %}
<input type="hidden" name="{{ key }}" value="{{ value }}" />
{% endfor %}
<div class="form-group">
<label class="control-label" for="id-goto-number">{% trans "Jump to position" %}</label>
<div class="controls">
<input type="number" min="1" max="{{ filter_count }}" value="{{ filter_pos }}" name="offset" id="id-goto-number">
</div>
</div>
<input type="submit" value="{% trans "Jump" %}" class="btn btn-primary" />
</form>
</div>

</div>
</li>
<li><a id="button-next" class="green" href="{{ next_unit_url }}" title="{% trans "Next" %}">{% if not LANGUAGE_BIDI %}{% icon "page-next.svg" %}{% else %}{% icon "page-previous.svg" %}{% endif %}</a></li>
<li><a id="button-end" class="green" href="{{ last_unit_url }}" title="{% trans "Last" %}">{% if not LANGUAGE_BIDI %}{% icon "page-last.svg" %}{% else %}{% icon "page-first.svg" %}{% endif %}</a></li>
</ul>
<div class="row query-container">
<div class="col-sm-9">
<form action="{{ unit.translation.get_translate_url }}" method="GET" class="result-page-form">
{% crispy search_form %}
</form>
</div>
<div class="col">
<div class="btn-group">
<ul class="pagination unit-navi">
<li>
<a id="button-first" class="green" href="{{ first_unit_url }}" title="{% trans "First" %}">{% if LANGUAGE_BIDI %}{% icon "page-last.svg" %}{% else %}{% icon "page-first.svg" %}{% endif %}</a>
</li>
<li>
<a id="button-prev" class="green" href="{{ prev_unit_url }}" title="{% trans "Previous" %}">{% if LANGUAGE_BIDI %}{% icon "page-next.svg" %}{% else %}{% icon "page-previous.svg" %}{% endif %}</a>
</li>
<li class="dropdown">
<a class="dropdown-toggle" data-toggle="dropdown" href="#" title="{% trans "Go to position" %}" id="goto-dropdown">
{% blocktrans %}{{ filter_pos }} / {{ filter_count }}{% endblocktrans %}
<span class="caret"></span>
</a>
<div class="dropdown-menu">
<div class="panel-group">
<form action="{{ unit.translation.get_translate_url }}" method="GET">
{% for key, value in search_items %}
<input type="hidden" name="{{ key }}" value="{{ value }}" aria-label="{{ value }}" />
{% endfor %}
<div class="form-group">
<label class="control-label" for="id-goto-number">{% trans "Jump to position" %}</label>
<div class="controls">
<input type="number" min="1" max="{{ filter_count }}" value="{{ filter_pos }}" name="offset" id="id-goto-number">
</div>
</div>
<input type="submit" value="{% trans "Jump" %}" class="btn btn-primary" aria-label="{% trans "Jump" %}" />
</form>
</div>
</div>
</li>
<li>
<a id="button-next" class="green" href="{{ next_unit_url }}" title="{% trans "Next" %}">{% if not LANGUAGE_BIDI %}{% icon "page-next.svg" %}{% else %}{% icon "page-previous.svg" %}{% endif %}</a>
</li>
<li>
<a id="button-end" class="green" href="{{ last_unit_url }}" title="{% trans "Last" %}">{% if not LANGUAGE_BIDI %}{% icon "page-last.svg" %}{% else %}{% icon "page-first.svg" %}{% endif %}</a>
</li>
</ul>
</div>
</div>
</div>

<div class="row">
Expand Down
Loading

0 comments on commit da0b288

Please sign in to comment.