Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pre-filter the 'Available' plugin manager tab, allow multiple terms #4580

Merged
merged 7 commits into from
Apr 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 41 additions & 3 deletions core/src/main/resources/hudson/PluginManager/_table.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#filter-box {
background: white url('search.gif') no-repeat 2px center;
padding-left: 20px;
padding-left: 35px;
width: 15em;
}

Expand All @@ -10,7 +9,7 @@ time {

#filter-container {
margin: 1em;
text-align: right;
font-size: 1em;
}
.plugin-manager__categories {
margin-top: 0.25em;
Expand All @@ -25,3 +24,42 @@ time {
padding: 0 0.5rem;
margin: 0 0.25rem 0.25rem 0;
}

.plugin-manager__search-input {
position: static;
padding: 0.25rem 0.1rem 0.25rem 2.5rem;
margin: 0;

font-size: 1rem;
line-height: 1.5;
color: #4d545d;
font-family: Roboto, Helvetica, Arial, sans-serif;

border-radius: 4px;
border: 1px solid grey;
outline: none;
}

.plugin-manager__search {
position: relative;
}

.plugin-manager__icon-leading {
position: absolute;
left: -2px;
top: -3px;
font-size: 15px;
padding: 0.5rem;
}

.main-search__icon-leading {
left: 0;
pointer-events: none;
}


.hidden-by-default {
}
.hidden {
display: none;
}
56 changes: 36 additions & 20 deletions core/src/main/resources/hudson/PluginManager/_table.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,30 +9,42 @@ function checkPluginsWithoutWarnings() {
}

Behaviour.specify("#filter-box", '_table', 0, function(e) {
function applyFilter() {
var filter = e.value.toLowerCase();
["TR.plugin","TR.plugin-category"].each(function(clz) {
var encountered = {};
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

encountered and TR.plugin-category have been obsolete since #4534.

var items = document.getElementsBySelector(clz);
for (var i=0; i<items.length; i++) {
var visible = (filter=="" || items[i].innerHTML.toLowerCase().indexOf(filter)>=0);
var name = items[i].cells && items[i].cells.length > 1
? items[i].cells[1].getAttribute('data-id')
: items[i].getAttribute("name");
if (visible && name != null) {
if (encountered[name]) {
visible = false;
}
encountered[name] = true;
function applyFilter() {
var filter = e.value.toLowerCase().trim();
var filterParts = filter.split(/ +/).filter (word => word.length > 0);
var items = document.getElementsBySelector("TR.plugin");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getElementsBySelector is a prototype.js function, and should be avoided. The alternatives are using querySelectorAll (https://caniuse.com/#search=querySelectorAll). If the browser support is not good enough (especially due to Baidu-browser support, then I suggest using getElementsByClassName('plugin') and filter out the elements that are not <tr> within the function.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unchanged from before, just threw out the other, obsolete selector ☹️

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I didn't read the diff properly then 👍

var anyVisible = false;
for (var i=0; i<items.length; i++) {
if ((filterParts.length < 1 || filter.length < 2) && items[i].hasClassName("hidden-by-default")) {
items[i].addClassName("hidden");
continue;
}
var makeVisible = true;

var content = items[i].innerHTML.toLowerCase();
for (var j = 0; j < filterParts.length; j++) {
var part = filterParts[j];
if (content.indexOf(part) < 0) {
makeVisible = false;
break;
}
items[i].style.display = (visible ? "" : "none");
}
});
if (makeVisible) {
items[i].removeClassName("hidden");
anyVisible = true;
} else {
items[i].addClassName("hidden");
}
}
var instructions = document.getElementById("hidden-by-default-instructions")
if (instructions) {
instructions.style.display = anyVisible ? 'none' : '';
}

layoutUpdateCallback.call();
}
layoutUpdateCallback.call();
}

e.onkeyup = applyFilter;
e.onkeyup = applyFilter;
});

/**
Expand Down Expand Up @@ -407,3 +419,7 @@ Behaviour.specify("#filter-box", '_table', 0, function(e) {
setEnableWidgetStates();
});
}());

Element.observe(window, "load", function() {
document.getElementById('filter-box').focus();
});
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,5 @@ THE SOFTWARE.
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<local:table page="available" list="${app.updateCenter.availables}" xmlns:local="/hudson/PluginManager" />
<local:table page="available" list="${app.updateCenter.availables}" filtered="true" xmlns:local="/hudson/PluginManager" />
</j:jelly>
15 changes: 12 additions & 3 deletions core/src/main/resources/hudson/PluginManager/installed.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,19 @@ THE SOFTWARE.
<st:include page="sidepanel.jelly"/>
<l:main-panel>
<st:adjunct includes="hudson.PluginManager._table"/>
<div id="filter-container">
${%Filter}:
<input type="text" id="filter-box"/>
<div id="filter-container">
<div class="plugin-manager__search">
<input
role="searchbox"
class="plugin-manager__search-input"
type="text"
id="filter-box"
placeholder="${filtered == 'true' ? '%search' : '%filter'}" />
<span class="plugin-manager__icon-leading">
<l:svgIcon href="${resURL}/images/material-icons/svg-sprite-action-symbol.svg#ic_search_24px" />
</span>
</div>
</div>

<j:if test="${app.updateCenter.isRestartRequiredForCompletion()}">
<div class="alert alert-warning"><strong>${%Warning}</strong>: ${%requires.restart}</div>
Expand Down
43 changes: 32 additions & 11 deletions core/src/main/resources/hudson/PluginManager/table.jelly
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,37 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->

<!--
Shared between index.jelly and available.jelly

Attributes:
list: variable to contain List<Plugin>
page: page name to be passed to local:tabBar
-->
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt">
<st:documentation>
<!-- Shared between PluginManager/index.jelly and PluginManager/available.jelly -->
<st:attribute name="list">
Variable to contain List of Plugin
</st:attribute>
<st:attribute name="page">
Page name to be passed to local:tabBar; 'updates' or 'available'.
</st:attribute>
<st:attribute name="filtered">
If true, will hide all rows by default, and only the filter field will show them.
</st:attribute>
</st:documentation>
<l:layout title="${%Update Center}" permission="${app.SYSTEM_READ}">
<st:include page="sidepanel.jelly"/>
<l:main-panel>
<st:adjunct includes="hudson.PluginManager._table"/>

<div id="filter-container">
${%Filter}:
<input type="text" id="filter-box"/>
<div class="plugin-manager__search">
<input
role="searchbox"
class="plugin-manager__search-input"
type="text"
id="filter-box"
placeholder="${filtered == 'true' ? '%search' : '%filter'}" />
<span class="plugin-manager__icon-leading">
<l:svgIcon href="${resURL}/images/material-icons/svg-sprite-action-symbol.svg#ic_search_24px" />
</span>
</div>
</div>

<form method="post" action="install">
Expand All @@ -60,11 +74,18 @@ THE SOFTWARE.
<j:choose>
<j:when test="${!empty(list)}">
<j:set var="cache" value="${it.createCache()}"/>
<j:if test="${filtered == 'true'}">
<tr id="hidden-by-default-instructions">
<td class="pane" colspan="5" align="center">
${%Use the search field above to search for available plugins.}
</td>
</tr>
</j:if>
<j:forEach var="p" items="${list}">
<j:set var="installJob" value="${isUpdates ? app.updateCenter.getJob(p) : null}" />
<j:set var="installedOk"
value="${installJob.status.success and installJob.plugin.version==p.version}" />
<tr class="${installJob!=null ? 'already-upgraded' : ''} plugin" name="${p.displayName}">
<tr class="${installJob!=null ? 'already-upgraded' : ''} plugin ${filtered == 'true' ? 'hidden hidden-by-default' : ''}" name="${p.displayName}">
<l:isAdmin>
<td class="pane" align="center">
<input type="checkbox" name="plugin.${p.name}.${p.sourceId}"
Expand Down