commit | author | age
|
4c13bf
|
1 |
/*
|
JM |
2 |
* Copyright 2012 gitblit.com.
|
|
3 |
*
|
|
4 |
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5 |
* you may not use this file except in compliance with the License.
|
|
6 |
* You may obtain a copy of the License at
|
|
7 |
*
|
|
8 |
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9 |
*
|
|
10 |
* Unless required by applicable law or agreed to in writing, software
|
|
11 |
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12 |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13 |
* See the License for the specific language governing permissions and
|
|
14 |
* limitations under the License.
|
|
15 |
*/
|
|
16 |
package com.gitblit.wicket.pages;
|
|
17 |
|
d04009
|
18 |
import java.text.MessageFormat;
|
4c13bf
|
19 |
import java.util.ArrayList;
|
JM |
20 |
import java.util.List;
|
|
21 |
|
31a897
|
22 |
import org.apache.wicket.Component;
|
4c13bf
|
23 |
import org.apache.wicket.PageParameters;
|
JM |
24 |
import org.apache.wicket.markup.html.basic.Label;
|
3d0494
|
25 |
import org.apache.wicket.markup.html.form.ListMultipleChoice;
|
4c13bf
|
26 |
import org.apache.wicket.markup.html.form.TextField;
|
31a897
|
27 |
import org.apache.wicket.markup.html.panel.Fragment;
|
4c13bf
|
28 |
import org.apache.wicket.markup.repeater.Item;
|
JM |
29 |
import org.apache.wicket.markup.repeater.data.DataView;
|
|
30 |
import org.apache.wicket.markup.repeater.data.ListDataProvider;
|
|
31 |
import org.apache.wicket.model.Model;
|
3f0677
|
32 |
import org.eclipse.jgit.lib.Constants;
|
4c13bf
|
33 |
|
3d0494
|
34 |
import com.gitblit.Constants.SearchType;
|
4c13bf
|
35 |
import com.gitblit.GitBlit;
|
d04009
|
36 |
import com.gitblit.Keys;
|
672296
|
37 |
import com.gitblit.models.RepositoryModel;
|
4c13bf
|
38 |
import com.gitblit.models.SearchResult;
|
672296
|
39 |
import com.gitblit.models.UserModel;
|
7d97c6
|
40 |
import com.gitblit.utils.ArrayUtils;
|
3f0677
|
41 |
import com.gitblit.utils.StringUtils;
|
672296
|
42 |
import com.gitblit.wicket.GitBlitWebSession;
|
ed295f
|
43 |
import com.gitblit.wicket.SessionlessForm;
|
672296
|
44 |
import com.gitblit.wicket.StringChoiceRenderer;
|
4c13bf
|
45 |
import com.gitblit.wicket.WicketUtils;
|
JM |
46 |
import com.gitblit.wicket.panels.LinkPanel;
|
d04009
|
47 |
import com.gitblit.wicket.panels.PagerPanel;
|
4c13bf
|
48 |
|
4e1930
|
49 |
public class LuceneSearchPage extends RootPage {
|
4c13bf
|
50 |
|
4e1930
|
51 |
public LuceneSearchPage() {
|
4c13bf
|
52 |
super();
|
JM |
53 |
setup(null);
|
|
54 |
}
|
|
55 |
|
4e1930
|
56 |
public LuceneSearchPage(PageParameters params) {
|
4c13bf
|
57 |
super(params);
|
JM |
58 |
setup(params);
|
|
59 |
}
|
|
60 |
|
|
61 |
private void setup(PageParameters params) {
|
|
62 |
setupPage("", "");
|
3d0494
|
63 |
|
7d97c6
|
64 |
// default values
|
JM |
65 |
ArrayList<String> repositories = new ArrayList<String>();
|
|
66 |
String query = "";
|
d04009
|
67 |
int page = 1;
|
JM |
68 |
int pageSize = GitBlit.getInteger(Keys.web.itemsPerPage, 50);
|
3d0494
|
69 |
|
JM |
70 |
if (params != null) {
|
7d97c6
|
71 |
String repository = WicketUtils.getRepositoryName(params);
|
JM |
72 |
if (!StringUtils.isEmpty(repository)) {
|
|
73 |
repositories.add(repository);
|
|
74 |
}
|
d04009
|
75 |
|
31a897
|
76 |
page = WicketUtils.getPage(params);
|
7d97c6
|
77 |
|
JM |
78 |
if (params.containsKey("repositories")) {
|
|
79 |
String value = params.getString("repositories", "");
|
|
80 |
List<String> list = StringUtils.getStringsFromValue(value);
|
|
81 |
repositories.addAll(list);
|
|
82 |
}
|
|
83 |
|
|
84 |
if (params.containsKey("query")) {
|
|
85 |
query = params.getString("query", "");
|
|
86 |
} else {
|
|
87 |
String value = WicketUtils.getSearchString(params);
|
|
88 |
String type = WicketUtils.getSearchType(params);
|
|
89 |
com.gitblit.Constants.SearchType searchType = com.gitblit.Constants.SearchType.forName(type);
|
|
90 |
if (!StringUtils.isEmpty(value)) {
|
|
91 |
if (searchType == SearchType.COMMIT) {
|
|
92 |
query = "type:" + searchType.name().toLowerCase() + " AND \"" + value + "\"";
|
|
93 |
} else {
|
|
94 |
query = searchType.name().toLowerCase() + ":\"" + value + "\"";
|
|
95 |
}
|
|
96 |
}
|
|
97 |
}
|
3d0494
|
98 |
}
|
JM |
99 |
|
40ca5c
|
100 |
// display user-accessible selections
|
JM |
101 |
UserModel user = GitBlitWebSession.get().getUser();
|
|
102 |
List<String> availableRepositories = new ArrayList<String>();
|
|
103 |
for (RepositoryModel model : GitBlit.self().getRepositoryModels(user)) {
|
|
104 |
if (model.hasCommits && !ArrayUtils.isEmpty(model.indexedBranches)) {
|
|
105 |
availableRepositories.add(model.name);
|
|
106 |
}
|
|
107 |
}
|
7db092
|
108 |
boolean luceneEnabled = GitBlit.getBoolean(Keys.web.allowLuceneIndexing, true);
|
JM |
109 |
if (luceneEnabled) {
|
|
110 |
if (availableRepositories.size() == 0) {
|
|
111 |
info(getString("gb.noIndexedRepositoriesWarning"));
|
|
112 |
}
|
|
113 |
} else {
|
|
114 |
error(getString("gb.luceneDisabled"));
|
40ca5c
|
115 |
}
|
JM |
116 |
|
|
117 |
// enforce user-accessible repository selections
|
|
118 |
ArrayList<String> searchRepositories = new ArrayList<String>();
|
|
119 |
for (String selectedRepository : repositories) {
|
|
120 |
if (availableRepositories.contains(selectedRepository)) {
|
|
121 |
searchRepositories.add(selectedRepository);
|
|
122 |
}
|
|
123 |
}
|
|
124 |
|
7d97c6
|
125 |
// search form
|
JM |
126 |
final Model<String> queryModel = new Model<String>(query);
|
40ca5c
|
127 |
final Model<ArrayList<String>> repositoriesModel = new Model<ArrayList<String>>(searchRepositories);
|
ed295f
|
128 |
SessionlessForm<Void> form = new SessionlessForm<Void>("searchForm", getClass()) {
|
7d97c6
|
129 |
|
JM |
130 |
private static final long serialVersionUID = 1L;
|
|
131 |
|
|
132 |
@Override
|
|
133 |
public void onSubmit() {
|
|
134 |
String q = queryModel.getObject();
|
|
135 |
if (StringUtils.isEmpty(q)) {
|
40ca5c
|
136 |
error(getString("gb.undefinedQueryWarning"));
|
7d97c6
|
137 |
return;
|
JM |
138 |
}
|
|
139 |
if (repositoriesModel.getObject().size() == 0) {
|
40ca5c
|
140 |
error(getString("gb.noSelectedRepositoriesWarning"));
|
7d97c6
|
141 |
return;
|
JM |
142 |
}
|
|
143 |
PageParameters params = new PageParameters();
|
|
144 |
params.put("repositories", StringUtils.flattenStrings(repositoriesModel.getObject()));
|
|
145 |
params.put("query", queryModel.getObject());
|
4e1930
|
146 |
setResponsePage(LuceneSearchPage.class, params);
|
7d97c6
|
147 |
}
|
JM |
148 |
};
|
40ca5c
|
149 |
|
672296
|
150 |
ListMultipleChoice<String> selections = new ListMultipleChoice<String>("repositories",
|
JM |
151 |
repositoriesModel, availableRepositories, new StringChoiceRenderer());
|
4e1930
|
152 |
selections.setMaxRows(8);
|
7db092
|
153 |
form.add(selections.setEnabled(luceneEnabled));
|
JM |
154 |
form.add(new TextField<String>("query", queryModel).setEnabled(luceneEnabled));
|
|
155 |
add(form.setEnabled(luceneEnabled));
|
7d97c6
|
156 |
|
JM |
157 |
// execute search
|
4c13bf
|
158 |
final List<SearchResult> results = new ArrayList<SearchResult>();
|
40ca5c
|
159 |
if (!ArrayUtils.isEmpty(searchRepositories) && !StringUtils.isEmpty(query)) {
|
d04009
|
160 |
results.addAll(GitBlit.self().search(query, page, pageSize, searchRepositories));
|
JM |
161 |
}
|
|
162 |
|
|
163 |
// results header
|
|
164 |
if (results.size() == 0) {
|
22a8a6
|
165 |
if (!ArrayUtils.isEmpty(searchRepositories) && !StringUtils.isEmpty(query)) {
|
JM |
166 |
add(new Label("resultsHeader", query).setRenderBodyOnly(true));
|
6caa93
|
167 |
add(new Label("resultsCount", getString("gb.noHits")).setRenderBodyOnly(true));
|
22a8a6
|
168 |
} else {
|
JM |
169 |
add(new Label("resultsHeader").setVisible(false));
|
|
170 |
add(new Label("resultsCount").setVisible(false));
|
|
171 |
}
|
d04009
|
172 |
} else {
|
JM |
173 |
add(new Label("resultsHeader", query).setRenderBodyOnly(true));
|
6caa93
|
174 |
add(new Label("resultsCount", MessageFormat.format(getString("gb.queryResults"),
|
d04009
|
175 |
results.get(0).hitId, results.get(results.size() - 1).hitId, results.get(0).totalHits)).
|
JM |
176 |
setRenderBodyOnly(true));
|
d896e6
|
177 |
}
|
7d97c6
|
178 |
|
JM |
179 |
// search results view
|
4c13bf
|
180 |
ListDataProvider<SearchResult> resultsDp = new ListDataProvider<SearchResult>(results);
|
JM |
181 |
final DataView<SearchResult> resultsView = new DataView<SearchResult>("searchResults", resultsDp) {
|
|
182 |
private static final long serialVersionUID = 1L;
|
|
183 |
public void populateItem(final Item<SearchResult> item) {
|
31a897
|
184 |
final SearchResult sr = item.getModelObject();
|
4c13bf
|
185 |
switch(sr.type) {
|
JM |
186 |
case commit: {
|
|
187 |
Label icon = WicketUtils.newIcon("type", "icon-refresh");
|
|
188 |
WicketUtils.setHtmlTooltip(icon, "commit");
|
|
189 |
item.add(icon);
|
98b4ed
|
190 |
item.add(new LinkPanel("summary", null, sr.summary, CommitPage.class, WicketUtils.newObjectParameter(sr.repository, sr.commitId)));
|
31a897
|
191 |
// show tags
|
JM |
192 |
Fragment fragment = new Fragment("tags", "tagsPanel", LuceneSearchPage.this);
|
|
193 |
List<String> tags = sr.tags;
|
|
194 |
if (tags == null) {
|
|
195 |
tags = new ArrayList<String>();
|
|
196 |
}
|
|
197 |
ListDataProvider<String> tagsDp = new ListDataProvider<String>(tags);
|
|
198 |
final DataView<String> tagsView = new DataView<String>("tag", tagsDp) {
|
|
199 |
private static final long serialVersionUID = 1L;
|
|
200 |
public void populateItem(final Item<String> item) {
|
|
201 |
String tag = item.getModelObject();
|
|
202 |
Component c = new LinkPanel("tagLink", null, tag, TagPage.class,
|
|
203 |
WicketUtils.newObjectParameter(sr.repository, Constants.R_TAGS + tag));
|
|
204 |
WicketUtils.setCssClass(c, "tagRef");
|
|
205 |
item.add(c);
|
|
206 |
}
|
|
207 |
};
|
|
208 |
fragment.add(tagsView);
|
|
209 |
item.add(fragment);
|
4c13bf
|
210 |
break;
|
JM |
211 |
}
|
|
212 |
case blob: {
|
|
213 |
Label icon = WicketUtils.newIcon("type", "icon-file");
|
|
214 |
WicketUtils.setHtmlTooltip(icon, "blob");
|
|
215 |
item.add(icon);
|
98b4ed
|
216 |
item.add(new LinkPanel("summary", null, sr.path, BlobPage.class, WicketUtils.newPathParameter(sr.repository, sr.branch, sr.path)));
|
31a897
|
217 |
item.add(new Label("tags").setVisible(false));
|
4c13bf
|
218 |
break;
|
JM |
219 |
}
|
|
220 |
case issue: {
|
|
221 |
Label icon = WicketUtils.newIcon("type", "icon-file");
|
|
222 |
WicketUtils.setHtmlTooltip(icon, "issue");
|
|
223 |
item.add(icon);
|
98b4ed
|
224 |
item.add(new Label("summary", "issue: " + sr.issueId));
|
31a897
|
225 |
item.add(new Label("tags").setVisible(false));
|
4c13bf
|
226 |
break;
|
JM |
227 |
}
|
|
228 |
}
|
98b4ed
|
229 |
item.add(new Label("fragment", sr.fragment).setEscapeModelStrings(false).setVisible(!StringUtils.isEmpty(sr.fragment)));
|
3f0677
|
230 |
item.add(new LinkPanel("repository", null, sr.repository, SummaryPage.class, WicketUtils.newRepositoryParameter(sr.repository)));
|
d04009
|
231 |
if (StringUtils.isEmpty(sr.branch)) {
|
JM |
232 |
item.add(new Label("branch", "null"));
|
|
233 |
} else {
|
|
234 |
item.add(new LinkPanel("branch", "branch", StringUtils.getRelativePath(Constants.R_HEADS, sr.branch), LogPage.class, WicketUtils.newObjectParameter(sr.repository, sr.branch)));
|
|
235 |
}
|
4c13bf
|
236 |
item.add(new Label("author", sr.author));
|
9adf62
|
237 |
item.add(WicketUtils.createDatestampLabel("date", sr.date, getTimeZone(), getTimeUtils()));
|
4c13bf
|
238 |
}
|
JM |
239 |
};
|
7d97c6
|
240 |
add(resultsView.setVisible(results.size() > 0));
|
d04009
|
241 |
|
JM |
242 |
PageParameters pagerParams = new PageParameters();
|
|
243 |
pagerParams.put("repositories", StringUtils.flattenStrings(repositoriesModel.getObject()));
|
|
244 |
pagerParams.put("query", queryModel.getObject());
|
|
245 |
|
697def
|
246 |
boolean showPager = false;
|
d04009
|
247 |
int totalPages = 0;
|
JM |
248 |
if (results.size() > 0) {
|
|
249 |
totalPages = (results.get(0).totalHits / pageSize) + (results.get(0).totalHits % pageSize > 0 ? 1 : 0);
|
697def
|
250 |
showPager = results.get(0).totalHits > pageSize;
|
d04009
|
251 |
}
|
JM |
252 |
|
697def
|
253 |
add(new PagerPanel("topPager", page, totalPages, LuceneSearchPage.class, pagerParams).setVisible(showPager));
|
JM |
254 |
add(new PagerPanel("bottomPager", page, totalPages, LuceneSearchPage.class, pagerParams).setVisible(showPager));
|
d04009
|
255 |
}
|
4c13bf
|
256 |
}
|