Skip to content

Commit

Permalink
Search now have history
Browse files Browse the repository at this point in the history
  • Loading branch information
judovana committed Mar 15, 2023
1 parent fef343c commit 8f85f5a
Show file tree
Hide file tree
Showing 7 changed files with 152 additions and 10 deletions.
15 changes: 14 additions & 1 deletion src/main/java/hudson/plugins/nested_view/NestedViewsSearch.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import hudson.model.TopLevelItem;
import hudson.model.View;
import hudson.plugins.nested_view.search.HelpItem;
import hudson.plugins.nested_view.search.HistoryItem;
import hudson.plugins.nested_view.search.NamableWithClass;
import hudson.plugins.nested_view.search.NestedViewsSearchResult;
import hudson.plugins.nested_view.search.Query;
Expand Down Expand Up @@ -34,7 +35,7 @@ public class NestedViewsSearch extends Search {

private static final long refreshTimeout = 10l * 60l * 1000l;
private static final int refreshAmount = 20;
private final static Logger LOGGER = Logger.getLogger(Search.class.getName());
public final static Logger LOGGER = Logger.getLogger(Search.class.getName());
private static transient volatile List<NamableWithClass> allCache = new ArrayList(0);
private static transient volatile int allTTL = 0;
private static transient volatile Date lastRefresh = new Date(0);
Expand Down Expand Up @@ -96,13 +97,25 @@ public void doIndex(StaplerRequest req, StaplerResponse rsp) throws IOException,
}
}
}
putToHistory(query, hits.size(), new Date());
}
Collections.sort(hits);
//todo, add paging &start=&count= .. defaulting to 0 and somwhere on 1000. Probably add next/prev links to jelly. Include `showing x/form` in jelly
RequestDispatcher v = req.getView(this, "search-results.jelly");
v.forward(req, rsp);
}

@SuppressFBWarnings(value = {"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"}, justification = "history is shared")
private void putToHistory(String query, int size, Date date) {
HistoryItem his = new HistoryItem(query.trim().replaceAll("\\s+", " "), size, date);
HistoryItem.add(his);
}

@SuppressFBWarnings(value = {"ST_WRITE_TO_STATIC_FROM_INSTANCE_METHOD"}, justification = "history is shared")
public List getHistory() {
return HistoryItem.get();
}

@Override
public SearchResult getSuggestions(final StaplerRequest req, @QueryParameter final String query) {
SearchResult suggestedItems = super.getSuggestions(req, query);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,13 @@ public LinkableCandidate toLinkable(String projectName) {
}
post = post + "/" + result + "/" + timeStampString + " ago";
;
return new LinkableCandidate(pre, link, post, Jenkins.get().getRootUrl().replaceAll("[\\/]+$", "") + "/job/" + projectName + "/" + id);
return new LinkableCandidate(pre, link, post, getJenkinsUrl() + "/job/" + projectName + "/" + id);
} else {
return new LinkableCandidate(prefix + "n/a");
}
}

public static String getJenkinsUrl() {
return Jenkins.get().getRootUrl().replaceAll("[\\/]+$", "");
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package hudson.plugins.nested_view.search;

import hudson.plugins.nested_view.ProjectWrapper;

// for some reasons, if class implements some interfaces, only methods from interface are available form jelly!
// thus this artificial interface...
public interface ExtendedSearch {
Expand Down
119 changes: 119 additions & 0 deletions src/main/java/hudson/plugins/nested_view/search/HistoryItem.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package hudson.plugins.nested_view.search;

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.plugins.nested_view.NestedViewsSearch;
import jenkins.model.Jenkins;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.stream.Collectors;

public class HistoryItem {

private static final int MAX_HISTORY = 500;
private static final File historyCache = new File(Jenkins.get().root, ".nested-view-serch.cache");
private static final List<HistoryItem> history = HistoryItem.load();

private final String query;
private final int size;
private final Date date;

@SuppressFBWarnings(value = {"EI_EXPOSE_REP2"}, justification = "date is not cared")
public HistoryItem(String query, int size, Date date) {
this.query = query;
this.size = size;
this.date = date;
}

public static void save() {
try {
saveImp();
} catch (Exception ex) {
NestedViewsSearch.LOGGER.log(Level.SEVERE, "saving nested view search history failed", ex);
}
}

public static void saveImp() throws IOException {
Files.write(historyCache.toPath(), history.stream().map(a -> a.toSave()).collect(Collectors.toList()));
}

public static List<HistoryItem> load() {
List<String> l = new ArrayList<>(0);
if (historyCache.exists()) try {
l = Files.readAllLines(historyCache.toPath());
} catch (Exception ex) {
NestedViewsSearch.LOGGER.log(Level.SEVERE, "loading nested view search history failed", ex);
}
ArrayList<HistoryItem> r = new ArrayList(MAX_HISTORY);
for (String s : l) {
try {
r.add(new HistoryItem(s));
} catch (Exception ex) {
NestedViewsSearch.LOGGER.log(Level.SEVERE, "reading nested view search history " + s + " failed", ex);
}
}
return Collections.synchronizedList(r);
}

public static List<HistoryItem> get() {
return Collections.unmodifiableList(history);
}

public static void add(HistoryItem his) {
history.removeAll(Collections.singleton(his));
history.add(0, his);
while (history.size() > MAX_HISTORY) {
history.remove(history.size() - 1);
}
save();
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
HistoryItem that = (HistoryItem) o;
return query.equals(that.query);
}

@Override
public int hashCode() {
return query.hashCode();
}

public String getQuery() {
return query;
}

public String getUrl() {
return BuildDetails.getJenkinsUrl() + "/search/?q=" + getQuery();
}

public int getSize() {
return size;
}

public String getDate() {
return new SimpleDateFormat("HH:mm:ss dd/MM").format(date);
}

public String toSave() {
return size + " " + date.getTime() + " " + query;
}

public HistoryItem(String saved) {
String[] sd = saved.split(" ");
size = Integer.parseInt(sd[0]);
date = new Date(Long.parseLong(sd[1]));
query = saved.replace(size + " " + date.getTime() + " ", "");

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import hudson.model.AbstractProject;
import hudson.plugins.nested_view.ProjectWrapper;
import hudson.search.SearchIndex;
import hudson.search.SearchItem;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package hudson.plugins.nested_view;
package hudson.plugins.nested_view.search;

import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -15,10 +15,6 @@
import hudson.model.AbstractProject;
import hudson.model.Result;
import hudson.model.Run;
import hudson.plugins.nested_view.search.BuildDetails;
import hudson.plugins.nested_view.search.LinkableCandidate;
import hudson.plugins.nested_view.search.NamableWithClass;
import hudson.plugins.nested_view.search.Query;

public class ProjectWrapper {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@
<l:layout title="${%Search for} '${q}'">
<l:side-panel>
<h2><l:icon class="icon-help icon-sm" /> Search help</h2>
<a onclick="document.getElementById('button_expand_2_1').style.display = 'none'; document.getElementById('button_collapse_2_1').style.display = 'inline'; document.getElementById('details_2_1').style.display = 'block'; return false;"
style="font-size: smaller; display: inline" href="#" id="button_expand_2_1">Search History (expand)</a>
<a onclick="document.getElementById('button_collapse_2_1').style.display = 'none';document.getElementById('details_2_1').style.display = 'none';document.getElementById('button_expand_2_1').style.display = 'inline'; return false;"
style="font-size: smaller; display: none" href="#" id="button_collapse_2_1">Search History (collapse)</a>
<div style="display: none" id="details_2_1">
<ol>
<j:forEach var="hist" items="${it.getHistory()}">
<li>
<a href="${hist.getUrl()}" >${hist.getQuery()}</a><st:nbsp/><small>found ${hist.getSize()} at ${hist.getDate()}</small>
</li>
</j:forEach>
</ol>
</div>
<h3>${%Supported keywords with an example}</h3>
<ol>
<j:forEach var="help" items="${it.getSearchHelp()}">
Expand Down

0 comments on commit 8f85f5a

Please sign in to comment.