Created
October 14, 2016 23:50
-
-
Save mathjazz/5cd6b4f9858a3e443ea4a041a3beba90 to your computer and use it in GitHub Desktop.
Improvements over PR #463
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/pontoon/base/models.py b/pontoon/base/models.py | |
index 27a997d..48184cb 100644 | |
--- a/pontoon/base/models.py | |
+++ b/pontoon/base/models.py | |
@@ -1323,7 +1323,7 @@ class Entity(DirtyFieldsMixin, models.Model): | |
@classmethod | |
def for_project_locale(self, project, locale, paths=None, status=None, | |
- search=None, exclude=None, smart=None, author=None, time=None): | |
+ search=None, exclude=None, extra=None, author=None, time=None): | |
"""Get project entities with locale translations.""" | |
entities = Entity.objects.all() | |
@@ -1355,14 +1355,14 @@ class Entity(DirtyFieldsMixin, models.Model): | |
if query: | |
entities = EntityQuerySet.with_status_counts(entities, locale).filter(query); | |
- if smart: | |
+ if extra: | |
query = None | |
- if ',' in smart: | |
- smart = smart.split(',') | |
+ if ',' in extra: | |
+ extra = extra.split(',') | |
else: | |
- smart = [smart] | |
+ extra = [extra] | |
- for s in smart: | |
+ for s in extra: | |
if s == 'untranslated': | |
q = (~Q(approved_count=F('expected_count'))) | |
diff --git a/pontoon/base/static/css/translate.css b/pontoon/base/static/css/translate.css | |
index c4d48f7..84a117f 100644 | |
--- a/pontoon/base/static/css/translate.css | |
+++ b/pontoon/base/static/css/translate.css | |
@@ -328,7 +328,7 @@ body > header .locale.select { | |
content: ""; | |
} | |
-.by-author .status:before { | |
+#filter .button.author .status:before { | |
color: #AAAAAA; | |
content: ""; | |
} | |
@@ -733,6 +733,10 @@ body > header aside p { | |
background: transparent; | |
} | |
+#filter .menu li.time-range .title { | |
+ display: none; | |
+} | |
+ | |
#filter .menu li.time-range label { | |
color: #FFFFFF; | |
float: left; | |
@@ -887,10 +891,15 @@ body > header aside p { | |
} | |
#filter .menu li.author { | |
+ height: 48px; | |
padding-left: 4px; | |
white-space: nowrap; | |
} | |
+#filter .menu li.author figure { | |
+ height: 100%; | |
+} | |
+ | |
#filter .menu li.author img { | |
vertical-align: top; | |
} | |
@@ -912,45 +921,63 @@ body > header aside p { | |
#filter .menu li.author .sel { | |
position: absolute; | |
- display: inline-block; | |
} | |
#filter .menu li.author .status { | |
display: none; | |
- position: absolute; | |
- line-height: 48px; | |
- left: 17px; | |
- top: auto; | |
+ height: 100%; | |
+ left: 0; | |
+ margin: 0; | |
+ padding: 16px 0 0; | |
+ text-align: center; | |
+ top: 0; | |
+ width: 100%; | |
z-index: 1; | |
+ | |
+ -moz-box-sizing: border-box; | |
+ box-sizing: border-box; | |
} | |
#filter .menu li.author .status:before { | |
color: #AAAAAA; | |
} | |
-#filter .menu li.author.selected .status, #filter .menu li.author:hover .status { | |
+ | |
+#filter .menu li.author.selected .status, | |
+#filter .menu li.author .sel:hover .status { | |
display: block; | |
} | |
-#filter .menu li.author.selected img, #filter .menu li.author:hover img { | |
+#filter .menu li.author.selected img, | |
+#filter .menu li.author .sel:hover img { | |
opacity: 0.3; | |
} | |
-#filter .apply-selected { | |
+#filter .toolbar { | |
display: none; | |
- background: #272A2F; | |
- border-bottom: 1px solid #5E6475; | |
- height: 44px; | |
- left: 0; | |
- padding: 12px; | |
- position: absolute; | |
- text-align: right; | |
+ border-top: 1px solid #5E6475; | |
+ margin-top: 12px; | |
+ padding: 12px 0 0; | |
text-transform: uppercase; | |
- width: 350px; | |
+ width: 100%; | |
+ | |
-moz-box-sizing: border-box; | |
box-sizing: border-box; | |
} | |
+#filter .clear-selection { | |
+ float: left; | |
+} | |
+ | |
+#filter .apply-selected { | |
+ float: right; | |
+ text-align: right; | |
+} | |
+ | |
+#filter .toolbar .fa { | |
+ vertical-align: top; | |
+} | |
+ | |
#filter .apply-selected:hover, #filter .apply-selected .applied-count { | |
color: #7BC876; | |
} | |
@@ -974,10 +1001,14 @@ body > header aside p { | |
top: 2px; | |
} | |
-#filter .menu li.unchanged .status { | |
+#filter .menu li.unchanged:not(.selected) .status { | |
left: 3px; | |
} | |
+#filter .menu li.unchanged:not(.selected) .status:hover { | |
+ left: 4px; | |
+} | |
+ | |
/* Make selection area bigger and fit the entire row for easier use */ | |
#filter .menu li .status { | |
margin: -3px -13px -3px -16px; | |
diff --git a/pontoon/base/static/css/user.css b/pontoon/base/static/css/user.css | |
index 4f03862..b5c1e60 100644 | |
--- a/pontoon/base/static/css/user.css | |
+++ b/pontoon/base/static/css/user.css | |
@@ -30,11 +30,6 @@ | |
opacity: 0.3; | |
} | |
-#title a img { | |
- transition: opacity 0.4s; | |
- -webkit-transition: opacity 0.4s; | |
-} | |
- | |
#subtitle .uneditable { | |
letter-spacing: normal; | |
padding: 8px 0 20px; | |
diff --git a/pontoon/base/static/js/main.js b/pontoon/base/static/js/main.js | |
index 86ef9a2..5fb1d39 100755 | |
--- a/pontoon/base/static/js/main.js | |
+++ b/pontoon/base/static/js/main.js | |
@@ -441,7 +441,6 @@ $(function() { | |
.parents('.select').addClass('opened'); | |
$('#iframe-cover:not(".hidden")').show(); // iframe fix | |
$('body:not(".admin-project") .menu:visible input[type=search]').focus().trigger('input'); | |
- $('.apply-selected').show(); | |
} | |
}); | |
diff --git a/pontoon/base/static/js/translate.js b/pontoon/base/static/js/translate.js | |
index 133ad92..c5f6bec 100644 | |
--- a/pontoon/base/static/js/translate.js | |
+++ b/pontoon/base/static/js/translate.js | |
@@ -15,18 +15,18 @@ var Pontoon = (function (my) { | |
/* | |
* Set filter widget | |
* | |
- * filter - object with properties 'status', 'smart', 'author', 'time' for each filter type | |
+ * filter - object with properties 'status', 'extra', 'author', 'time' for each filter type | |
*/ | |
- setFilters: function (filter) { | |
+ setFilter: function (filter) { | |
filter = filter || { | |
status: [], | |
- smart: [], | |
- author: [], | |
- time: '' | |
+ extra: [], | |
+ time: '', | |
+ author: [] | |
}; | |
- var node = $('#filter .menu [data-type="' + (filter.smart || filter.status) + '"]'), | |
- selectorType = filter.smart || filter.status; | |
+ var selectorType = filter.extra.length ? filter.extra : filter.status, | |
+ node = $('#filter .menu [data-type="' + selectorType + '"]'); | |
function defaultFilter() { | |
selectorType = 'all'; | |
@@ -36,25 +36,25 @@ var Pontoon = (function (my) { | |
// Validate filter | |
if (node.length === 0) { | |
- var t = filter.time; | |
+ var time = filter.time; | |
// Special case: filter by time range | |
- if (/^[0-9]{12}-[0-9]{12}$/.test(t)) { | |
+ if (/^[0-9]{12}-[0-9]{12}$/.test(time)) { | |
// Populate from/to inputs (needed if filter specified in URL) | |
var from = new Date( | |
- t.substring(0, 4) + '/' + | |
- t.substring(4, 6) + '/' + | |
- t.substring(6, 8) + ' ' + | |
- t.substring(8, 10) + ':' + | |
- t.substring(10, 12) + ' UTC' | |
+ time.substring(0, 4) + '/' + | |
+ time.substring(4, 6) + '/' + | |
+ time.substring(6, 8) + ' ' + | |
+ time.substring(8, 10) + ':' + | |
+ time.substring(10, 12) + ' UTC' | |
); | |
var to = new Date( | |
- t.substring(13, 17) + '/' + | |
- t.substring(17, 19) + '/' + | |
- t.substring(19, 21) + ' ' + | |
- t.substring(21, 23) + ':' + | |
- t.substring(23, 25) + ' UTC' | |
+ time.substring(13, 17) + '/' + | |
+ time.substring(17, 19) + '/' + | |
+ time.substring(19, 21) + ' ' + | |
+ time.substring(21, 23) + ':' + | |
+ time.substring(23, 25) + ' UTC' | |
); | |
if (from != 'Invalid Date' && to != 'Invalid Date') { | |
@@ -72,6 +72,7 @@ var Pontoon = (function (my) { | |
this.resetTimeRange(); | |
} | |
+ // If filter invalid, fallback to default | |
} else { | |
defaultFilter(); | |
} | |
@@ -80,13 +81,9 @@ var Pontoon = (function (my) { | |
var title = node.find('.title').text(); | |
// Special case: filter by one author | |
- if (filter.author.length == 1) { | |
- title = $('#filter .menu [data-type="' + filter.author[0] + '"]').find('.name').text() + '\'s translations'; | |
- selectorType = 'by-author'; | |
- } | |
- | |
- if (selectorType == 'time-range'){ | |
- title = 'Time Range'; | |
+ if (filter.author.length === 1) { | |
+ title = $('#filter .menu [data-type="' + filter.author[0] + '"]').find('.name').text() + "'s translations"; | |
+ selectorType = 'author'; | |
} | |
$('#search').attr('placeholder', 'Search in ' + title); | |
@@ -1044,94 +1041,103 @@ var Pontoon = (function (my) { | |
/* | |
- * Turns on/off .selected class and changes placeholder & icon of multiple filters search | |
+ * Mark selected filters | |
*/ | |
- applySelectedFilters: function(){ | |
- var f = this.getFilter(), | |
- applied = 0, | |
- types = 0, | |
- l = 0, | |
- title = '', | |
- type = 'all'; | |
+ updateMultipleFilterSelection: function() { | |
+ var filter = this.getFilter(), | |
+ typeFilterCount = 0, | |
+ placeholder = [], | |
+ selectorType = 'all'; | |
- $('#filter .selected').removeClass('selected'); | |
- for (var i in f) { | |
- if (f[i]) { | |
- if (f[i] == 'untranslated') { | |
- $('#filter .menu [data-type="missing"], #filter .menu [data-type="fuzzy"], #filter .menu [data-type="suggested"]').addClass("selected"); | |
+ // Reset all filters | |
+ this.clearSelectedFilters(); | |
+ | |
+ function markSelectedFilters(type) { | |
+ for (var i=0; i < typeFilterCount; i++) { | |
+ var node = $('#filter .menu [data-type="' + filter[type][i] + '"]'), | |
+ title = node.find('.title').text(); | |
+ | |
+ node.addClass('selected'); | |
+ | |
+ if (type === 'author') { | |
+ title = node.find('.name').text() + "'s translations"; | |
} | |
+ placeholder.push(title); | |
+ } | |
+ } | |
- if (i == 'status') { | |
- l = f.status.length; | |
- if (l > 0) types++; | |
- if (l > 1) title = 'Search in ' + f.status.join(', ') + ' strings'; | |
- for (var a = 0; a < l; a++) { | |
- $('#filter .menu [data-type="' +f.status[a] + '"]').addClass("selected"); | |
- applied++; | |
- } | |
+ for (var type in filter) { | |
+ if (filter[type] && filter[type] !== []) { | |
+ typeFilterCount = filter[type].length; | |
- } else if (i == 'smart') { | |
- l = f.smart.length; | |
- if (l > 0) types++; | |
- if (l > 1) title = 'Search ' + f.smart.map(function(v){ | |
- return v == 'has-suggestions' ? 'having suggestions' : v; | |
- }).join(', ') + ' strings'; | |
- for (var a = 0; a < l; a++) { | |
- $('#filter .menu [data-type="' +f.smart[a] + '"]').addClass("selected"); | |
- applied++; | |
- } | |
+ if (type === 'status' || type === 'extra' || type === 'author') { | |
+ markSelectedFilters(type); | |
- } else if (i == 'author') { | |
- l = f.author.length; | |
- if (l > 0) types++; | |
- if (l > 1){ | |
- title = 'Search translations of ' + f.author.join(', '); | |
- type = 'by-author'; | |
- } | |
- for (var a = 0; a < l; a++) { | |
- $('#filter .menu [data-type="' + f.author[a] + '"]').addClass("selected"); | |
- applied++; | |
- } | |
+ } else if (type === 'time') { | |
+ var node = $('#filter .menu [data-type="time-range"]'); | |
+ node.addClass('selected'); | |
+ placeholder.push(node.find('.title').text()); | |
- } else { | |
- $('#filter .menu [data-type="time-range"]').addClass("selected"); | |
- applied++; | |
- types++; | |
} | |
} | |
} | |
- if (types > 1) { | |
- title = 'Search using ' + types + ' combined filters'; | |
- type = 'all'; | |
- } | |
+ var selectedCount = $('#filter .selected').length; | |
- if (title) { | |
- $('#search').attr('placeholder', title); | |
- $('#filter .button').attr('class', 'button selector ' + type); | |
+ // If only one filter selected, use it's own icon in the filter selector | |
+ if (selectedCount === 1) { | |
+ selectorType = $('#filter .selected').data('type'); | |
+ if (selectorType.indexOf('@') !== -1) { | |
+ selectorType = 'author'; | |
+ } | |
} | |
- $('.apply-selected') | |
- .find('.variant').toggleClass('plural', applied > 1).parent() | |
- .find('.applied-count').html(applied); | |
+ // Update placeholder and filter selector icon | |
+ $('#search').attr('placeholder', 'Search in ' + (placeholder.join(', ') || 'All')); | |
+ $('#filter .button').attr('class', 'button selector ' + selectorType); | |
- return applied; | |
+ // Update count (N) in Apply N filters button | |
+ $('#filter .toolbar') | |
+ .toggle(selectedCount > 0) | |
+ .find('.variant').toggleClass('plural', selectedCount > 1).end() | |
+ .find('.applied-count').html(selectedCount); | |
}, | |
- validateDate: function() { | |
+ | |
+ /* | |
+ * Validate Time range filter | |
+ */ | |
+ validateTimeRange: function() { | |
var from = this.local2server($('#from').val()); | |
to = this.local2server($('#to').val()); | |
- // Validate Time range filter | |
if (from && to) { | |
- return from + '-' + to; | |
+ return from + '-' + to; | |
} else { | |
- $('#from').toggleClass('error', !from); | |
- $('#to').toggleClass('error', !to); | |
- return ''; | |
+ $('#from').toggleClass('error', !from); | |
+ $('#to').toggleClass('error', !to); | |
+ return false; | |
} | |
}, | |
+ | |
+ /* | |
+ * Clear selected filters | |
+ */ | |
+ clearSelectedFilters: function() { | |
+ $('#filter .selected').removeClass('selected'); | |
+ }, | |
+ | |
+ | |
+ /* | |
+ * Apply selected filters | |
+ */ | |
+ applySelectedFilters: function() { | |
+ this.searchEntities(); | |
+ $('#filter .selector').click(); | |
+ }, | |
+ | |
+ | |
attachEntityListHandlers: function() { | |
var self = this; | |
@@ -1139,77 +1145,80 @@ var Pontoon = (function (my) { | |
$('#filter').on('click', 'li[data-type]:not(".editing"):not(".all") .status', function(e) { | |
e.stopPropagation(); | |
- var filter = self.getFilter(), | |
- el = $(this).parent(), | |
- el = el.data('type') ? el : el.parent().parent(), | |
+ var el = $(this).parents('li'), | |
value = el.data('type'), | |
- applied = 0; | |
+ filter = self.getFilter(), | |
+ num = null; | |
+ | |
+ function updateFilterValue(type) { | |
+ num = $.inArray(value, filter[type]); | |
+ if (num === -1) { | |
+ filter[type].push(value); | |
+ } else { | |
+ filter[type].splice(num, 1); | |
+ } | |
+ } | |
if (el.hasClass('time-range')) { | |
- filter.time = el.hasClass('selected') ? '' : self.validateDate(); | |
+ filter.time = el.hasClass('selected') ? '' : self.validateTimeRange() || ''; | |
} else if (el.hasClass('author')) { | |
- var num = $.inArray(value, filter.author); | |
- (num == -1) ? filter.author.push(value) : filter.author.splice(num, 1); | |
+ updateFilterValue('author'); | |
} else if (el.hasClass('untranslated') || el.hasClass('unchanged') || el.hasClass('has-suggestions')) { | |
- var num = $.inArray(value, filter.smart); | |
- (num == -1) ? filter.smart.push(value) : filter.smart.splice(num, 1); | |
- if (filter.smart == 'untranslated') filter.status = []; | |
+ updateFilterValue('extra'); | |
} else { | |
- var num = $.inArray('untranslated', filter.smart); | |
- if ((num !=- 1) && (value == 'missing' || value == 'fuzzy' || value == 'suggested')) { | |
- var a = ['missing', 'fuzzy', 'suggested']; | |
- a.splice($.inArray(value, a), 1); | |
- filter.status.push(a[0], a[1]); | |
- filter.smart.splice(num, 1); | |
- | |
- } else { | |
- var num = $.inArray(value, filter.status); | |
- (num == -1) ? filter.status.push(value) : filter.status.splice(num, 1); | |
- | |
- } | |
+ updateFilterValue('status'); | |
} | |
- self.setFilters(filter); | |
- self.applySelectedFilters(); | |
+ self.updateMultipleFilterSelection(); | |
}); | |
- // Use ONLY ONE filter for entities | |
+ // Filter entities by a single filter | |
$('#filter').on('click', 'li[data-type]:not(".editing")', function(e) { | |
var el = $(this), | |
value = el.data('type'), | |
filter = { | |
status: [], | |
- smart: [], | |
- author: [], | |
- time: '' | |
+ extra: [], | |
+ time: '', | |
+ author: [] | |
}; | |
if (el.hasClass('time-range')) { | |
- filter.time = self.validateDate(); | |
+ filter.time = self.validateTimeRange(); | |
+ if (!filter.time) { | |
+ return; | |
+ } | |
} else if (el.hasClass('author')) { | |
filter.author.push(value); | |
} else if (el.hasClass('untranslated') || el.hasClass('unchanged') || el.hasClass('has-suggestions')) { | |
- filter.smart.push(value); | |
+ filter.extra.push(value); | |
- } else if(!el.hasClass('all')) { | |
+ } else if (!el.hasClass('all')) { | |
filter.status.push(value); | |
} | |
- self.setFilters(filter); | |
+ self.clearSelectedFilters(); | |
+ self.setFilter(filter); | |
self.applySelectedFilters(); | |
- self.searchEntities(); | |
- $('#filter .selector').click(); | |
+ }); | |
+ | |
+ // Clear selected filters | |
+ $('#filter .clear-selected').click(function(e) { | |
+ e.preventDefault(); | |
+ | |
+ self.clearSelectedFilters(); | |
+ self.setFilter(); | |
+ $('#filter .toolbar').hide(); | |
}); | |
// Apply selected filters | |
$('#filter .apply-selected').click(function(e) { | |
- self.searchEntities(); | |
- $('#filter .selector').click(); | |
+ self.applySelectedFilters(); | |
}); | |
// Time range editing toggle | |
@@ -1833,7 +1842,7 @@ var Pontoon = (function (my) { | |
self.updateCachedTranslation(); | |
self.updateAuthors(); | |
self.updateRangePicker(); | |
- self.applySelectedFilters(); | |
+ self.updateMultipleFilterSelection(); | |
} | |
}); | |
}, | |
@@ -1958,7 +1967,7 @@ var Pontoon = (function (my) { | |
self.updateAuthors(); | |
self.countsPerMinute = entitiesData.counts_per_minute; | |
self.updateRangePicker(); | |
- self.applySelectedFilters(); | |
+ self.updateMultipleFilterSelection(); | |
entitiesMap = {}; | |
$.each(entitiesData.entities, function() { | |
@@ -2263,7 +2272,7 @@ var Pontoon = (function (my) { | |
self.updateAuthors(); | |
self.updateInPlaceTranslation(data.translation.string); | |
self.updateRangePicker(); | |
- self.applySelectedFilters(); | |
+ self.updateMultipleFilterSelection(); | |
// Update translation, including in place if possible | |
if (entity.body && (self.user.isTranslator || !entity.translation[pf].approved)) { | |
@@ -2462,7 +2471,6 @@ var Pontoon = (function (my) { | |
// Hide menus on click outside | |
$('body').bind("click.main", function (e) { | |
$('.menu').hide(); | |
- $('.apply-selected').hide(); | |
$('#iframe-cover').hide(); // iframe fix | |
$('.select').removeClass('opened'); | |
$('.menu li').removeClass('hover'); | |
@@ -2588,7 +2596,7 @@ var Pontoon = (function (my) { | |
self.updateCurrentPart(self.getSelectedPart()); | |
// Reset optional state parameters and update state | |
- self.setFilters(); | |
+ self.setFilter(); | |
self.setSearch(''); | |
var state = self.getState('selected'); | |
@@ -2640,7 +2648,7 @@ var Pontoon = (function (my) { | |
*/ | |
updateAuthors: function () { | |
var authors = $('#filter').find('.for-authors').toggle(this.authors.length > 0); | |
- $('#filter .author').remove(); | |
+ $('#filter .menu li.author').remove(); | |
$.each(this.authors, function() { | |
authors.after('<li class="author" data-type="' + this.email + '">' + | |
@@ -2774,7 +2782,7 @@ var Pontoon = (function (my) { | |
self.resetTimeRange(); | |
self.updateAuthors(); | |
self.updateRangePicker(); | |
- self.applySelectedFilters(); | |
+ self.updateMultipleFilterSelection(); | |
self.renderEntityList(); | |
self.updateProgress(); | |
@@ -2806,7 +2814,7 @@ var Pontoon = (function (my) { | |
entity = this.state.entity; | |
// No optional state parameters | |
- if (!filter.status && !filter.smart && !filter.author && !filter.time && !search && !entity) { | |
+ if (!filter.status && !filter.extra && !filter.author && !filter.time && !search && !entity) { | |
this.showDefaultView(); | |
return; | |
} | |
@@ -3261,7 +3269,7 @@ var Pontoon = (function (my) { | |
'paths': self.getPartPaths(self.currentPart), | |
'search': self.getSearch(), | |
'status': self.getFilter('status').join(','), | |
- 'smart': self.getFilter('smart').join(','), | |
+ 'extra': self.getFilter('extra').join(','), | |
'author': self.getFilter('author').join(','), | |
'time': self.getFilter('time'), | |
'inplaceEditor': self.requiresInplaceEditor() | |
@@ -3313,7 +3321,7 @@ var Pontoon = (function (my) { | |
self.updateProgress(); | |
self.updateAuthors(); | |
self.updateRangePicker(); | |
- self.applySelectedFilters(); | |
+ self.updateMultipleFilterSelection(); | |
self.createObject(true); | |
return; | |
} | |
@@ -3609,8 +3617,8 @@ var Pontoon = (function (my) { | |
queryParams.status = state.filter.status.join(','); | |
} | |
- if (state.filter.smart.length > 0) { | |
- queryParams.smart = state.filter.smart.join(','); | |
+ if (state.filter.extra.length > 0) { | |
+ queryParams.extra = state.filter.extra.join(','); | |
} | |
if (state.filter.author.length > 0) { | |
@@ -3679,18 +3687,18 @@ var Pontoon = (function (my) { | |
updateInitialState: function() { | |
var state = this.getState('selected'); | |
state.filter = { | |
- status: this.getQueryParam('status') ? this.getQueryParam('status').split(',') : [], | |
- smart: this.getQueryParam('smart') ? this.getQueryParam('smart').split(',') : [], | |
- author: this.getQueryParam('author') ? this.getQueryParam('author').split(',') : [], | |
- time: this.getQueryParam('time') | |
+ status: this.getQueryParam('status') ? this.getQueryParam('status').split(',') : [], | |
+ extra: this.getQueryParam('extra') ? this.getQueryParam('extra').split(',') : [], | |
+ time: this.getQueryParam('time'), | |
+ author: this.getQueryParam('author') ? this.getQueryParam('author').split(',') : [] | |
}; | |
state.search = this.getQueryParam('search'); | |
state.entity = this.getQueryParam('string'); | |
// Update search and filter | |
this.setSearch(state.search); | |
- this.setFilters(state.filter); | |
- this.applySelectedFilters(); | |
+ this.setFilter(state.filter); | |
+ this.updateMultipleFilterSelection(); | |
// Fallback to first available part if no matches found (mistyped URL) | |
var paths = requestedPaths = this.getSelectedPart(); | |
@@ -3729,8 +3737,8 @@ window.onpopstate = function(e) { | |
// Update search and filter | |
Pontoon.setSearch(Pontoon.state.search); | |
- Pontoon.setFilters(Pontoon.state.filter); | |
- Pontoon.applySelectedFilters(); | |
+ Pontoon.setFilter(Pontoon.state.filter); | |
+ Pontoon.updateMultipleFilterSelection(); | |
Pontoon.initializePart(true); | |
} | |
@@ -3751,9 +3759,10 @@ Pontoon.attachBatchEditorHandlers(); | |
Pontoon.authors = $('#server').data('authors'); | |
Pontoon.updateAuthors(); | |
+ | |
Pontoon.countsPerMinute = $('#server').data('counts-per-minute'); | |
Pontoon.updateRangePicker(); | |
-Pontoon.applySelectedFilters(); | |
+Pontoon.updateMultipleFilterSelection(); | |
Pontoon.updateInitialState(); | |
Pontoon.initializePart(); | |
diff --git a/pontoon/base/templates/translate.html b/pontoon/base/templates/translate.html | |
index c41938c..e108428 100755 | |
--- a/pontoon/base/templates/translate.html | |
+++ b/pontoon/base/templates/translate.html | |
@@ -146,20 +146,11 @@ | |
<div id="entitylist"> | |
<div class="search-wrapper clearfix"> | |
<div class="icon fa fa-search"></div> | |
- <input id="search" type="search" autocomplete="off" placeholder="Search All" title="Search Strings (Ctrl + Shift + F)"> | |
+ <input id="search" type="search" autocomplete="off" placeholder="Search in All" title="Search Strings (Ctrl + Shift + F)"> | |
<div id="filter" class="select" data-current-filter="all"> | |
<div class="button selector all"> | |
<span class="status fa"></span> | |
</div> | |
- <a class="apply-selected" href="#apply-selected" title="Apply Selected Filters"> | |
- <span class="fa fa-check fa-lg"></span> | |
- Apply | |
- <span class="applied-count"></span> | |
- <span class="variant"> | |
- <span class="singular">filter</span> | |
- <span class="plural">filters</span> | |
- </span> | |
- </a> | |
<div class="menu"> | |
<ul> | |
<li class="horizontal-separator">Translation Status</li> | |
@@ -170,7 +161,7 @@ | |
{{ Filter.item('suggested', 'Suggested', count=True) }} | |
{{ Filter.item('translated', 'Translated', count=True) }} | |
- <li class="horizontal-separator">Smart Filters</li> | |
+ <li class="horizontal-separator">Extra Filters</li> | |
{{ Filter.item('untranslated', 'Untranslated') }} | |
{{ Filter.item('unchanged', 'Unchanged') }} | |
@@ -180,7 +171,8 @@ | |
<li class="time-range clearfix" data-type="time-range"> | |
<span class="status fa"></span> | |
- <div class="title clearfix"> | |
+ <span class="title">Time Range</span> | |
+ <div class="clearfix"> | |
<label for="from">From<input type="datetime" id="from" disabled></label> | |
<label for="to">To<input type="datetime" id="to" disabled></label> | |
</div> | |
@@ -189,6 +181,21 @@ | |
<li class="horizontal-separator for-authors">Translation Authors</li> | |
</ul> | |
+ <div class="toolbar clearfix"> | |
+ <a class="clear-selected" href="#clear-filters" title="Uncheck selected filters"> | |
+ <span class="fa fa-remove fa-lg"></span> | |
+ Clear selection | |
+ </a> | |
+ <a class="apply-selected" href="#apply-filters" title="Apply Selected Filters"> | |
+ <span class="fa fa-check fa-lg"></span> | |
+ Apply | |
+ <span class="applied-count"></span> | |
+ <span class="variant"> | |
+ <span class="singular">filter</span> | |
+ <span class="plural">filters</span> | |
+ </span> | |
+ </a> | |
+ </div> | |
</div> | |
</div> | |
</div> | |
diff --git a/pontoon/base/views.py b/pontoon/base/views.py | |
index d51d255..8c5e65e 100755 | |
--- a/pontoon/base/views.py | |
+++ b/pontoon/base/views.py | |
@@ -412,7 +412,7 @@ def entities(request): | |
locale = get_object_or_404(Locale, code__iexact=locale) | |
status = request.POST.get('status', '') | |
- smart = request.POST.get('smart', '') | |
+ extra = request.POST.get('extra', '') | |
author = request.POST.get('author', '') | |
time = request.POST.get('time', '') | |
search = request.POST.get('search', '') | |
@@ -437,7 +437,7 @@ def entities(request): | |
}, safe=False) | |
entities = Entity.for_project_locale( | |
- project, locale, paths, status, search, exclude_entities, smart, author, time | |
+ project, locale, paths, status, search, exclude_entities, extra, author, time | |
) | |
# Only return a list of entity PKs (batch editing: select all) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment