From 7b7bf964dff5de34a09b4b733ab3308cb0b68e7f Mon Sep 17 00:00:00 2001 From: Alexander Todorov Date: Thu, 14 Nov 2024 23:01:18 +0200 Subject: [PATCH] More speed-up for TestCase filtering on the TestPlan view page building upon the previous change we now either show or hide rows on screen depending on what the actual result set is. When the rows which match the filter are less than the ones which don't we display only them. Else we display everything and hide the rows which don't match the filter. This always results in the minimum number of display updates. For the extreme scenario where 990/1000 rows match is_automated=false this provides 30x improvement! WARNING: for scenarios which are not on the extreme case, yet still result in 100s of rows that need to be displayed this commit does not offer any optimization compared to the previous one! --- tcms/testplans/static/testplans/js/get.js | 51 ++++++++++++++++++++--- 1 file changed, 45 insertions(+), 6 deletions(-) diff --git a/tcms/testplans/static/testplans/js/get.js b/tcms/testplans/static/testplans/js/get.js index 3064065d3e..08c64dd7d6 100644 --- a/tcms/testplans/static/testplans/js/get.js +++ b/tcms/testplans/static/testplans/js/get.js @@ -688,6 +688,47 @@ function getSelectedTestCases () { return tcIds } +// returns 2 arrays with selectors that need to be either shown or hidden +// return values will be used as multiple-selector for jQuery +// see https://api.jquery.com/multiple-selector/ +function findSelectorsToShowAndHide (inputData, filterBy, filterValue) { + const hideMe = [] + const showMe = [] + + inputData.forEach(function (element) { + if (element[filterBy] !== undefined && element[filterBy].toString().toLowerCase().indexOf(filterValue) > -1) { + showMe.push(`[data-testcase-pk=${element.id}]`) + } else { + hideMe.push(`[data-testcase-pk=${element.id}]`) + } + }) + + return { + hide: hideMe, + show: showMe + } +} + +// update the screen in one swoop trying to perform +// as little display updates as possible +function showOrHideMultipleRows (rootSelector, rows) { + // initial state is that everything is hidden + + if (rows.show.length <= rows.hide.length) { + $(rows.show.join(',')).show() + } else { + /* eslint-disable indent */ + $('body') + .find(rootSelector) + .show() + .end() + .find(rows.hide.join(',')) + .hide() + .end() + /* eslint-enable */ + } +} + function filterTestCasesByProperty (planId, testCases, filterBy, filterValue) { // no input => show all rows if (filterValue.trim().length === 0) { @@ -697,8 +738,6 @@ function filterTestCasesByProperty (planId, testCases, filterBy, filterValue) { $('.js-testcase-row').hide() - // see https://api.jquery.com/multiple-selector/ - const showOnly = [] if (filterBy === 'component' || filterBy === 'tag') { const query = { plan: planId } query[`${filterBy}__name__icontains`] = filterValue @@ -706,15 +745,15 @@ function filterTestCasesByProperty (planId, testCases, filterBy, filterValue) { jsonRPC('TestCase.filter', query, function (filtered) { // hide again if a previous async request showed something else $('.js-testcase-row').hide() + + const showOnly = [] filtered.forEach(tc => showOnly.push(`[data-testcase-pk=${tc.id}]`)) $(showOnly.join(',')).show() }) } else { - testCases.filter(function (tc) { - return (tc[filterBy] !== undefined && tc[filterBy].toString().toLowerCase().indexOf(filterValue) > -1) - }).forEach(tc => showOnly.push(`[data-testcase-pk=${tc.id}]`)) + const rows = findSelectorsToShowAndHide(testCases, filterBy, filterValue) - $(showOnly.join(',')).show() + showOrHideMultipleRows('.js-testcase-row', rows) } }