You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@drill.apache.org by gp...@apache.org on 2019/01/04 06:54:00 UTC
[drill] 05/10: DRILL-6921: Add Clear button for /options filter
This is an automated email from the ASF dual-hosted git repository.
gparai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/drill.git
commit 8a85879507866a83293812205ceab2591391c590
Author: Kunal Khatua <kk...@maprtech.com>
AuthorDate: Tue Jan 1 10:10:07 2019 -0800
DRILL-6921: Add Clear button for /options filter
This commit adds the following search enhancements:
1. Addition of a clear ('x') button in the search field
2. If a filter term has been entered in the search box, on clicking the Update or Reset-to-Default button of any option, the reloaded page will re-apply the last entered filter term in the search box.
3. If the search box is empty, on clicking the Update or Reset-to-Default button of any option, the reloaded page will automatically filter out everything except the updated/reset option to show the changed value.
4. Customization of the quick search terms. (using defaults in drill-module.conf)
closes #1588
---
.../java/org/apache/drill/exec/ExecConstants.java | 2 +
.../drill/exec/server/rest/StatusResources.java | 55 ++++++++++++++++++----
.../java-exec/src/main/resources/drill-module.conf | 3 +-
exec/java-exec/src/main/resources/rest/options.ftl | 50 ++++++++++++++------
4 files changed, 86 insertions(+), 24 deletions(-)
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
index afa29d9..77cfb9f 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/ExecConstants.java
@@ -224,6 +224,8 @@ public final class ExecConstants {
public static final String HTTP_AUTHENTICATION_MECHANISMS = "drill.exec.http.auth.mechanisms";
public static final String HTTP_SPNEGO_PRINCIPAL = "drill.exec.http.auth.spnego.principal";
public static final String HTTP_SPNEGO_KEYTAB = "drill.exec.http.auth.spnego.keytab";
+ //Customize filters in options
+ public static final String HTTP_WEB_OPTIONS_FILTERS = "drill.exec.http.web.options.filters";
public static final String SYS_STORE_PROVIDER_CLASS = "drill.exec.sys.store.provider.class";
public static final String SYS_STORE_PROVIDER_LOCAL_PATH = "drill.exec.sys.store.provider.local.path";
public static final String SYS_STORE_PROVIDER_LOCAL_ENABLE_WRITE = "drill.exec.sys.store.provider.local.write";
diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/StatusResources.java b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/StatusResources.java
index 1ebef31..9123b65 100644
--- a/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/StatusResources.java
+++ b/exec/java-exec/src/main/java/org/apache/drill/exec/server/rest/StatusResources.java
@@ -17,6 +17,7 @@
*/
package org.apache.drill.exec.server.rest;
+import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
@@ -31,13 +32,16 @@ import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.SecurityContext;
+import javax.ws.rs.core.UriInfo;
import javax.xml.bind.annotation.XmlRootElement;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
+import org.apache.drill.exec.ExecConstants;
import org.apache.drill.exec.server.options.OptionList;
import org.apache.drill.exec.server.options.OptionManager;
import org.apache.drill.exec.server.options.OptionValue;
@@ -63,6 +67,8 @@ public class StatusResources {
public static final String PATH_INTERNAL_OPTIONS_JSON = "/internal_options" + REST_API_SUFFIX;
public static final String PATH_OPTIONS = "/options";
public static final String PATH_INTERNAL_OPTIONS = "/internal_options";
+ //Used to access current filter state in WebUI
+ private static final String CURRENT_FILTER_PARAM = "filter";
@Inject UserAuthEnabled authEnabled;
@Inject WorkManager work;
@@ -118,27 +124,35 @@ public class StatusResources {
return getSystemOptionsJSONHelper(true);
}
- private Viewable getSystemOptionsHelper(boolean internal) {
+ //Generate model-view for WebUI (PATH_OPTIONS and PATH_INTERNAL_OPTIONS)
+ private Viewable getSystemOptionsHelper(boolean internal, UriInfo uriInfo) {
+ List<OptionWrapper> options = getSystemOptionsJSONHelper(internal);
+ List<String> fltrList = new ArrayList<>(work.getContext().getConfig().getStringList(ExecConstants.HTTP_WEB_OPTIONS_FILTERS));
+ String currFilter = (uriInfo != null) ? uriInfo.getQueryParameters().getFirst(CURRENT_FILTER_PARAM) : null;
+ if (currFilter == null) {
+ currFilter = "";
+ }
+
return ViewableWithPermissions.create(authEnabled.get(),
"/rest/options.ftl",
sc,
- getSystemOptionsJSONHelper(internal));
+ new OptionsListing(options, fltrList, currFilter));
}
@GET
@Path(StatusResources.PATH_OPTIONS)
@RolesAllowed(DrillUserPrincipal.AUTHENTICATED_ROLE)
@Produces(MediaType.TEXT_HTML)
- public Viewable getSystemPublicOptions() {
- return getSystemOptionsHelper(false);
+ public Viewable getSystemPublicOptions(@Context UriInfo uriInfo) {
+ return getSystemOptionsHelper(false, uriInfo);
}
@GET
@Path(StatusResources.PATH_INTERNAL_OPTIONS)
@RolesAllowed(DrillUserPrincipal.AUTHENTICATED_ROLE)
@Produces(MediaType.TEXT_HTML)
- public Viewable getSystemInternalOptions() {
- return getSystemOptionsHelper(true);
+ public Viewable getSystemInternalOptions(@Context UriInfo uriInfo) {
+ return getSystemOptionsHelper(true, uriInfo);
}
@SuppressWarnings("resource")
@@ -160,9 +174,34 @@ public class StatusResources {
}
if (optionManager.getOptionDefinition(name).getMetaData().isInternal()) {
- return getSystemInternalOptions();
+ return getSystemInternalOptions(null);
} else {
- return getSystemPublicOptions();
+ return getSystemPublicOptions(null);
+ }
+ }
+
+ /**
+ * Data Model for rendering /options on webUI
+ */
+ public static class OptionsListing {
+ private final List<OptionWrapper> options;
+ private final List<String> filters;
+ private final String dynamicFilter;
+
+ public OptionsListing(List<OptionWrapper> optList, List<String> fltrList, String currFilter) {
+ this.options = optList;
+ this.filters = fltrList;
+ this.dynamicFilter = currFilter;
+ }
+
+ public List<OptionWrapper> getOptions() {
+ return options;
+ }
+ public List<String> getFilters() {
+ return filters;
+ }
+ public String getDynamicFilter() {
+ return dynamicFilter;
}
}
diff --git a/exec/java-exec/src/main/resources/drill-module.conf b/exec/java-exec/src/main/resources/drill-module.conf
index 3682a85..e792b20 100644
--- a/exec/java-exec/src/main/resources/drill-module.conf
+++ b/exec/java-exec/src/main/resources/drill-module.conf
@@ -155,7 +155,8 @@ drill.exec: {
reservation: 0,
maximum: 9223372036854775807
}
- }
+ },
+ web.options.filters: ["planner", "store", "parquet", "hashagg", "hashjoin"]
},
//setting javax variables for ssl configurations is being deprecated.
ssl: {
diff --git a/exec/java-exec/src/main/resources/rest/options.ftl b/exec/java-exec/src/main/resources/rest/options.ftl
index a8e03fa..1fce03c 100644
--- a/exec/java-exec/src/main/resources/rest/options.ftl
+++ b/exec/java-exec/src/main/resources/rest/options.ftl
@@ -24,8 +24,18 @@
<script>
//Alter System Values
function alterSysOption(optionName, optionValue, optionKind) {
+ var currHref = location.href;
+ var redirectHref = currHref.replace(/(.?filter=).*/,"");
+ //Read filter value and apply to reload with new filter
+ var reApplyFilter = $("#searchBox").val();
+ if (reApplyFilter != null && reApplyFilter.trim().length > 0) {
+ redirectHref = redirectHref + "?filter=" + reApplyFilter.trim();
+ } else { //Apply filter for updated field
+ redirectHref = redirectHref + "?filter=" + optionName;
+ }
$.post("/option/"+optionName, {kind: optionKind, name: optionName, value: optionValue}, function () {
- location.reload(true);
+ //Remove existing filters
+ location.href=redirectHref;
});
}
@@ -71,16 +81,19 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
<#macro page_body>
<div class="page-header">
</div>
- <div class="btn-group btn-group-sm" style="display:inline-block;">
- <button type="button" class="btn" style="cursor:default;font-weight:bold;" > Quick Filters </button>
- <button type="button" class="btn btn-info" onclick="inject(this.innerHTML);">planner</button>
- <button type="button" class="btn btn-info" onclick="inject(this.innerHTML);">store</button>
- <button type="button" class="btn btn-info" onclick="inject(this.innerHTML);">parquet</button>
- <button type="button" class="btn btn-info" onclick="inject(this.innerHTML);">hashagg</button>
- <button type="button" class="btn btn-info" onclick="inject(this.innerHTML);">hashjoin</button>
- </div>
<div class="col-xs-4">
- <input id="searchBox" name="searchBox" class="form-control" type="text" value="" placeholder="Search options...">
+ <div class="input-group input-sm" >
+ <input id="searchBox" name="searchBox" class="form-control" type="text" value="" placeholder="Search options...">
+ <div class="input-group-btn">
+ <button class="btn btn-default" type="button" onclick="$('#searchBox').val('').focus();" title="Clear search" style="font-weight:bold">×</button>
+ </div>
+ </div>
+ </div>
+ <div class="btn-group btn-group-sm" style="padding-top:0.5%;">
+ <button type="button" class="btn" style="cursor:default;font-weight:bold;" > Quick Filters </button>
+ <#list model.getFilters() as filter>
+ <button type="button" class="btn btn-info" onclick="inject(this.innerHTML);">${filter}</button>
+ </#list>
</div>
<div class="table-responsive">
@@ -92,9 +105,7 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
<th style="width:45%">DESCRIPTION</th>
</tr>
</thead>
- <tbody>
- <#assign i = 1>
- <#list model as option>
+ <tbody><#assign i = 1><#list model.getOptions() as option>
<tr id="row-${i}">
<td style="font-family:Courier New; vertical-align:middle" id='optionName'>${option.getName()}</td>
<td>
@@ -142,7 +153,7 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
"infoEmpty": "No options available",
"infoFiltered": ""
}
- } );
+ });
//Draw when the table is ready
$(document).ready(function() {
@@ -156,10 +167,19 @@ table.sortable thead .sorting_desc { background-image: url("/static/img/black-de
// Draw DataTable
optTable.rows().invalidate().draw();
+
+ //Re-Inject Filter keyword here
+ let explicitFltr = "";
+ if (window.location.search.indexOf("filter=") >= 1) {
+ //Select 1st occurrence (Chrome accepts 1st of duplicates)
+ let kvPair=window.location.search.substr(1).split('&')[0];
+ explicitFltr=kvPair.split('=')[1]
+ inject(explicitFltr);
+ }
});
//EventListener to update table when changes are detected
- $('#searchBox').on('keyup change', function () {
+ $('#searchBox').on('keyup focus change', function () {
optTable.search(this.value).draw().toString();
});