You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@drill.apache.org by GitBox <gi...@apache.org> on 2019/01/04 06:54:07 UTC

[GitHub] gparai closed pull request #1588: DRILL-6921: Add Clear button for /options filter

gparai closed pull request #1588: DRILL-6921: Add Clear button for /options filter
URL: https://github.com/apache/drill/pull/1588
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

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 afa29d902e3..77cfb9f60de 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 @@ private 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 1ebef313e24..9123b656e7c 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.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 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 int compare(OptionWrapper o1, OptionWrapper o2) {
     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 Viewable updateSystemOption(@FormParam("name") String name,
     }
 
     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 3682a855fa0..e792b205803 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 a8e03fa461e..1fce03ca590 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">&times;</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();
     });
 


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services