Permalink
Browse files

make fields selection survive pagination and link sharing

a list of the selected fields is now transported through the controller
in addition the query fragment is used to select the shown fields to allow sharing the url directly

only direct searches are preserved right now, the handling of saved searches, new searches, resetting the field list, CSV exports etc need more work

issue #610
  • Loading branch information...
1 parent 3d196c7 commit e55ff4e8427341c7efb981ec67f2265424361329 @kroepke kroepke committed Mar 3, 2014
@@ -23,7 +23,7 @@
public class OpenSearchController extends BaseController {
public static Result index() {
- final String relative = routes.SearchController.index("{searchTerms}", "relative", 3600, "", "", "", "", 1, "", "", "").absoluteURL(request());
+ final String relative = routes.SearchController.index("{searchTerms}", "relative", 3600, "", "", "", "", 1, "", "", "", "").absoluteURL(request());
final String unescaped = relative.replaceAll("%7B", "{").replaceAll("%7D", "}").replaceAll("&", "&");
String content =
"<OpenSearchDescription xmlns=\"http://a9.com/-/spec/opensearch/1.1/\"\n" +
@@ -109,7 +109,8 @@ private Call callFromSavedSearch(SavedSearch search, String streamId, boolean in
0,
searchId,
"",
- ""
+ "",
+ "" // TODO fields
);
} else {
return routes.StreamSearchController.index(
@@ -124,7 +125,8 @@ private Call callFromSavedSearch(SavedSearch search, String streamId, boolean in
0,
searchId,
"",
- ""
+ "",
+ "" // TODO fields
);
}
}
@@ -18,7 +18,10 @@
*/
package controllers;
+import com.google.common.base.Splitter;
+import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
import com.google.common.net.MediaType;
import com.google.inject.Inject;
import lib.APIException;
@@ -36,6 +39,7 @@
import java.io.IOException;
import java.util.List;
+import java.util.Set;
public class SearchController extends AuthenticatedController {
@@ -50,14 +54,25 @@
public Result globalSearch() {
// User would not be allowed to do any global searches anyway, so we can redirect him to the streams page to avoid confusion.
- if (Permissions.isPermitted(RestPermissions.SEARCHES_ABSOLUTE) || Permissions.isPermitted(RestPermissions.SEARCHES_RELATIVE) || Permissions.isPermitted(RestPermissions.SEARCHES_KEYWORD)) {
+ if (Permissions.isPermitted(RestPermissions.SEARCHES_ABSOLUTE)
+ || Permissions.isPermitted(RestPermissions.SEARCHES_RELATIVE)
+ || Permissions.isPermitted(RestPermissions.SEARCHES_KEYWORD)) {
return ok(views.html.search.global.render(currentUser()));
} else {
return redirect(routes.StreamsController.index());
}
}
- public Result index(String q, String rangeType, int relative, String from, String to, String keyword, String interval, int page, String savedSearchId, String sortField, String sortOrder) {
+ public Result index(String q,
+ String rangeType,
+ int relative,
+ String from, String to,
+ String keyword,
+ String interval,
+ int page,
+ String savedSearchId,
+ String sortField, String sortOrder,
+ String fields) {
SearchSort sort = buildSearchSort(sortField, sortOrder);
UniversalSearch search;
@@ -72,6 +87,7 @@ public Result index(String q, String rangeType, int relative, String from, Strin
SearchResult searchResult;
DateHistogramResult histogramResult;
SavedSearch savedSearch;
+ Set<String> selectedFields = getSelectedFields(fields);
try {
if(savedSearchId != null && !savedSearchId.isEmpty()) {
savedSearch = savedSearchService.get(savedSearchId);
@@ -86,7 +102,7 @@ public Result index(String q, String rangeType, int relative, String from, Strin
searchResult = search.search();
if (searchResult.getError() != null) {
- return ok(views.html.search.queryerror.render(currentUser(), q, searchResult, savedSearch, null));
+ return ok(views.html.search.queryerror.render(currentUser(), q, searchResult, savedSearch, fields, null));
}
searchResult.setAllFields(getAllFields());
@@ -99,12 +115,22 @@ public Result index(String q, String rangeType, int relative, String from, Strin
}
if (searchResult.getTotalResultCount() > 0) {
- return ok(views.html.search.results.render(currentUser(), search, searchResult, histogramResult, q, page, savedSearch, null));
+ return ok(views.html.search.results.render(currentUser(), search, searchResult, histogramResult, q, page, savedSearch, selectedFields, null));
} else {
- return ok(views.html.search.noresults.render(currentUser(), q, searchResult, savedSearch, null));
+ return ok(views.html.search.noresults.render(currentUser(), q, searchResult, savedSearch, selectedFields, null));
}
}
+ protected Set<String> getSelectedFields(String fields) {
+ Set<String> selectedFields = Sets.newHashSet();
+ if (fields != null && !fields.isEmpty()) {
+ Iterables.addAll(selectedFields, Splitter.on(',').split(fields));
+ } else {
+ selectedFields.addAll(Field.STANDARD_SELECTED_FIELDS);
+ }
+ return selectedFields;
+ }
+
public Result exportAsCsv(String q, String filter, String rangeType, int relative, String from, String to, String keyword) {
UniversalSearch search;
try {
@@ -11,6 +11,7 @@
import play.mvc.Result;
import java.io.IOException;
+import java.util.Set;
/**
* @author Dennis Oelkers <dennis@torch.sh>
@@ -19,7 +20,15 @@
@Inject
private StreamService streamService;
- public Result index(String streamId, String q, String rangeType, int relative, String from, String to, String keyword, String interval, int page, String savedSearchId, String sortField, String sortOrder) {
+ public Result index(String streamId,
+ String q,
+ String rangeType, int relative,
+ String from, String to,
+ String keyword, String interval,
+ int page,
+ String savedSearchId,
+ String sortField, String sortOrder,
+ String fields) {
SearchSort sort = buildSearchSort(sortField, sortOrder);
Stream stream;
@@ -58,6 +67,7 @@ public Result index(String streamId, String q, String rangeType, int relative, S
SearchResult searchResult;
DateHistogramResult histogramResult;
SavedSearch savedSearch;
+ Set<String> selectedFields = getSelectedFields(fields);
try {
if(savedSearchId != null && !savedSearchId.isEmpty()) {
savedSearch = savedSearchService.get(savedSearchId);
@@ -72,7 +82,7 @@ public Result index(String streamId, String q, String rangeType, int relative, S
searchResult = search.search();
if (searchResult.getError() != null) {
- return ok(views.html.search.queryerror.render(currentUser(), q, searchResult, savedSearch, stream));
+ return ok(views.html.search.queryerror.render(currentUser(), q, searchResult, savedSearch, fields, stream));
}
searchResult.setAllFields(getAllFields());
@@ -85,9 +95,9 @@ public Result index(String streamId, String q, String rangeType, int relative, S
}
if (searchResult.getTotalResultCount() > 0) {
- return ok(views.html.search.results.render(currentUser(), search, searchResult, histogramResult, q, page, savedSearch, stream));
+ return ok(views.html.search.results.render(currentUser(), search, searchResult, histogramResult, q, page, savedSearch, selectedFields, stream));
} else {
- return ok(views.html.search.noresults.render(currentUser(), q, searchResult, savedSearch, stream));
+ return ok(views.html.search.noresults.render(currentUser(), q, searchResult, savedSearch, selectedFields, stream));
}
}
View
@@ -18,20 +18,19 @@
*/
package lib;
+import com.google.common.collect.ImmutableSet;
+import org.apache.commons.codec.binary.Hex;
+
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Set;
-import org.apache.commons.codec.binary.Hex;
-
-import com.google.common.collect.ImmutableSet;
-
public class Field {
private final String name;
private final String hash;
- private final static Set<String> STANDARD_SELECTED_FIELDS = ImmutableSet.of(
+ public final static Set<String> STANDARD_SELECTED_FIELDS = ImmutableSet.of(
"source",
"message"
);
@@ -60,5 +59,5 @@ public String getHash() {
public boolean isStandardSelected() {
return STANDARD_SELECTED_FIELDS.contains(name);
}
-
+
}
View
@@ -163,22 +163,18 @@ public long getTotalConnections() {
return getGaugeValue("total_connections");
}
- @Deprecated
public long getReadBytes() {
return getGaugeValue(buildNetworkIOMetricName("read_bytes", false));
}
- @Deprecated
public long getWrittenBytes() {
return getGaugeValue(buildNetworkIOMetricName("written_bytes", false));
}
- @Deprecated
public long getTotalReadBytes() {
return getGaugeValue(buildNetworkIOMetricName("read_bytes", true));
}
- @Deprecated
public long getTotalWrittenBytes() {
return getGaugeValue(buildNetworkIOMetricName("written_bytes", true));
}
@@ -53,7 +53,7 @@ public Startpage(Type type, String id) {
public Call getCall() {
switch (type) {
case STREAM:
- return routes.StreamSearchController.index(id, "*", "relative", 3600, "", "", "", "", 0, "", "", "");
+ return routes.StreamSearchController.index(id, "*", "relative", 3600, "", "", "", "", 0, "", "", "", ""); // TODO fields
case DASHBOARD:
return routes.DashboardsController.show(id);
default:
@@ -201,6 +201,7 @@ public Call getRoute(Request request, int page, String sortField, String sortOrd
String to = Tools.stringSearchParamOrEmpty(request, "to");
String keyword = Tools.stringSearchParamOrEmpty(request, "keyword");
String interval = Tools.stringSearchParamOrEmpty(request, "interval");
+ String fields = Tools.stringSearchParamOrEmpty(request, "fields");
// TODO we desperately need to pass the streamid and then build the filter here, instead of passing the filter and then trying to reassemble the streamid.
if (filter != null && filter.startsWith("streams:")) {
@@ -216,7 +217,8 @@ public Call getRoute(Request request, int page, String sortField, String sortOrd
page,
"",
sortField,
- sortOrder
+ sortOrder,
+ fields
);
} else {
return routes.SearchController.index(
@@ -230,7 +232,8 @@ public Call getRoute(Request request, int page, String sortField, String sortOrd
page,
"",
sortField,
- sortOrder
+ sortOrder,
+ fields
);
}
}
@@ -25,13 +25,11 @@
import lib.DateTools;
import lib.timeranges.InvalidRangeParametersException;
import lib.timeranges.TimeRange;
-import models.Stream;
import models.api.requests.dashboards.WidgetUpdateRequest;
import models.api.responses.dashboards.DashboardWidgetResponse;
import models.api.responses.dashboards.DashboardWidgetValueResponse;
import models.dashboards.Dashboard;
import org.joda.time.DateTime;
-import play.Logger;
import play.mvc.Call;
import java.io.IOException;
@@ -230,7 +228,8 @@ protected Call prepareNonStreamBoundReplayRoute(String query, TimeRange timerang
0,
"",
"",
- ""
+ "",
+ "" // TODO fields
);
}
@@ -247,7 +246,8 @@ protected Call prepareStreamBoundReplayRoute(String streamId, String query, Time
0,
"",
"",
- ""
+ "",
+ "" // TODO fields
);
}
@@ -23,6 +23,7 @@
<script src="@routes.Assets.at("javascripts/Rickshaw.Graph.Graylog2Selector.js")" type="text/javascript"></script>
<script src="@routes.Assets.at("javascripts/Rickshaw.Fixtures.Graylog2Time.js")" type="text/javascript"></script>
<script src="@routes.Assets.at("javascripts/URI.js")" type="text/javascript"></script>
+<script src="@routes.Assets.at("javascripts/URI.fragmentQuery.js")" type="text/javascript"></script>
<script src="@routes.Assets.at("javascripts/validations.js")" type="text/javascript"></script>
<script src="@routes.Assets.at("javascripts/toastr.js")" type="text/javascript"></script>
<script src="@routes.Assets.at("javascripts/store.min.js")" type="text/javascript"></script>
@@ -1,4 +1,4 @@
-@(currentUser: User, query: String, searchResult: models.api.results.SearchResult, savedSearch: SavedSearch)(implicit stream: Stream)
+@(currentUser: User, query: String, searchResult: models.api.results.SearchResult, savedSearch: SavedSearch, fields: Set[String])(implicit stream: Stream)
@main("Search results", sidebars.standard(currentUser), query, currentUser) {
@@ -1,4 +1,4 @@
-@(currentUser: User, query: String, searchResult: models.api.results.SearchResult, savedSearch: SavedSearch)(implicit stream: Stream)
+@(currentUser: User, query: String, searchResult: models.api.results.SearchResult, savedSearch: SavedSearch, fields: String)(implicit stream: Stream)
@import views.helpers.QueryErrorHelper
@import models.api.responses.SearchResultResponse.GenericError
Oops, something went wrong.

3 comments on commit e55ff4e

Contributor

lennartkoopmann replied Mar 3, 2014

are there follow up tickets for the missing functionality? (just asking because it's so easy to forget that)

Contributor

lennartkoopmann replied Mar 3, 2014

something else that I though about initially was using localstorage for this: the fields you selected are stored in localstorage and thus survive switching between streams or coming back to search results later.

Contributor

kroepke replied Mar 4, 2014

No haven't created the followup tickets, I think I left the original open for that.

Please sign in to comment.