Merge pull request #1047 from yyjdelete/patch-1

Use utf-8 for Javadoc
diff --git a/src/main/java/com/gitblit/wicket/WicketUtils.java b/src/main/java/com/gitblit/wicket/WicketUtils.java
index d9ff34a..99c1e08 100644
--- a/src/main/java/com/gitblit/wicket/WicketUtils.java
+++ b/src/main/java/com/gitblit/wicket/WicketUtils.java
@@ -417,6 +417,19 @@
 		return new PageParameters(parameterMap);

 	}

 

+	public static PageParameters newFilestorePageParameter(int pageNumber, String filter) {

+		Map<String, String> parameterMap = new HashMap<String, String>();

+		

+		if (pageNumber > 1) {

+			parameterMap.put("pg", String.valueOf(pageNumber));

+		}

+		if (filter != null) {

+			parameterMap.put("s", String.valueOf(filter));

+		}

+		

+		return new PageParameters(parameterMap);

+	}

+

 	public static PageParameters newBlobDiffParameter(String repositoryName,

 			String baseCommitId, String commitId, String path) {

 		Map<String, String> parameterMap = new HashMap<String, String>();

diff --git a/src/main/java/com/gitblit/wicket/pages/FilestorePage.html b/src/main/java/com/gitblit/wicket/pages/FilestorePage.html
index e373e70..8b917e8 100644
--- a/src/main/java/com/gitblit/wicket/pages/FilestorePage.html
+++ b/src/main/java/com/gitblit/wicket/pages/FilestorePage.html
@@ -8,8 +8,18 @@
 <wicket:extend>
 <div class="container">
 	
-	<div class="markdown" style="padding: 10px 0px 5px 0px;">
-		<span wicket:id="repositoriesMessage">[repositories message]</span>
+	<div style="padding: 10px 0px 5px 0px;">
+		<table class="filestore-status">
+			<tr>
+				<td><a wicket:id="filterByOk" href="#"><span wicket:id="statusOkIcon"></span><span wicket:id="statusOkCount"></span></a></td>
+				<td><a wicket:id="filterByPending" href="#"><span wicket:id="statusPendingIcon"></span><span wicket:id="statusPendingCount"></span></a></td>
+				<td><a wicket:id="filterByInprogress" href="#"><span wicket:id="statusInprogressIcon"></span><span wicket:id="statusInprogressCount"></span></a></td>
+				<td><a wicket:id="filterByError" href="#"><span wicket:id="statusErrorIcon"></span><span wicket:id="statusErrorCount"></span></a></td>
+				<td><a wicket:id="filterByDeleted" href="#"><span wicket:id="statusDeletedIcon"></span><span wicket:id="statusDeletedCount"></span></a></td>
+				<td></td>
+				<td><span class="fa fa-fw fa-database"></span><span wicket:id="spaceAvailable"></span></td>
+			</tr>
+		</table>
 		<span style="float:right"><a href="#" wicket:id="filestoreHelp"><span wicket:id="helpMessage">[help message]</span></a></span>
 	</div>
 	
@@ -31,7 +41,14 @@
        		</tr>
     	</tbody>
 	</table>
+	
+	<!-- pager links -->
+	<div style="padding-bottom:5px;">
+		<a wicket:id="firstPageBottom"><wicket:message key="gb.pageFirst"></wicket:message></a> | <a wicket:id="prevPageBottom">&laquo; <wicket:message key="gb.pagePrevious"></wicket:message></a> | <a wicket:id="nextPageBottom"><wicket:message key="gb.pageNext"></wicket:message> &raquo;</a> 
+	</div>
 </div>
+
+	
 </wicket:extend>
 </body>
 </html>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/FilestorePage.java b/src/main/java/com/gitblit/wicket/pages/FilestorePage.java
index 7c3bb9d..7130f6c 100644
--- a/src/main/java/com/gitblit/wicket/pages/FilestorePage.java
+++ b/src/main/java/com/gitblit/wicket/pages/FilestorePage.java
@@ -16,13 +16,12 @@
 package com.gitblit.wicket.pages;
 
 import java.text.DateFormat;
-import java.text.MessageFormat;
 import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.io.FileUtils;
-import org.apache.wicket.Component;
+import org.apache.wicket.PageParameters;
 import org.apache.wicket.markup.html.basic.Label;
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;
 import org.apache.wicket.markup.repeater.Item;
@@ -30,7 +29,9 @@
 import org.apache.wicket.markup.repeater.data.ListDataProvider;
 
 import com.gitblit.Constants;
+import com.gitblit.Keys;
 import com.gitblit.models.FilestoreModel;
+import com.gitblit.models.FilestoreModel.Status;
 import com.gitblit.models.UserModel;
 import com.gitblit.wicket.CacheControl;
 import com.gitblit.wicket.FilestoreUI;
@@ -47,10 +48,22 @@
 @CacheControl(LastModified.ACTIVITY)
 public class FilestorePage extends RootPage {
 
-	public FilestorePage() {
-		super();
+	public FilestorePage(PageParameters params) {
+		super(params);
 		setupPage("", "");
 
+		int itemsPerPage = app().settings().getInteger(Keys.web.itemsPerPage, 20);
+		if (itemsPerPage <= 1) {
+			itemsPerPage = 20;
+		}
+		
+		final int pageNumber = WicketUtils.getPage(params);
+		final String filter = WicketUtils.getSearchString(params);
+		
+		int prevPage = Math.max(0, pageNumber - 1);
+		int nextPage = pageNumber + 1;
+		boolean hasMore = false;
+		
 		final UserModel user = (GitBlitWebSession.get().getUser() == null) ? UserModel.ANONYMOUS : GitBlitWebSession.get().getUser();
 		final long nBytesUsed = app().filestore().getFilestoreUsedByteCount();
 		final long nBytesAvailable = app().filestore().getFilestoreAvailableByteCount();
@@ -59,21 +72,88 @@
 		if (files == null) {
 			files = new ArrayList<FilestoreModel>();
 		}
+
+		long nOk = 0;
+		long nPending = 0;
+		long nInprogress = 0;
+		long nError = 0;
+		long nDeleted = 0;
 		
-		String message = MessageFormat.format(getString("gb.filestoreStats"), files.size(),
-				FileUtils.byteCountToDisplaySize(nBytesUsed), FileUtils.byteCountToDisplaySize(nBytesAvailable) );
+		for (FilestoreModel file : files) {
+			switch (file.getStatus()) {
+			case Available: { nOk++;} break;
+			case Upload_Pending: { nPending++; } break;
+			case Upload_In_Progress: { nInprogress++; } break;
+			case Deleted: { nDeleted++; } break;
+			default: { nError++; } break;
+			}
+		}
+		
+		
+		BookmarkablePageLink<Void> itemOk = new BookmarkablePageLink<Void>("filterByOk", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(prevPage, SortBy.ok.name()));
+		
+		BookmarkablePageLink<Void> itemPending = new BookmarkablePageLink<Void>("filterByPending", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(prevPage, SortBy.pending.name()));
+		
+		BookmarkablePageLink<Void> itemInprogress = new BookmarkablePageLink<Void>("filterByInprogress", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(prevPage, SortBy.inprogress.name()));
+		
+		BookmarkablePageLink<Void> itemError = new BookmarkablePageLink<Void>("filterByError", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(prevPage, SortBy.error.name()));
 
-		Component repositoriesMessage = new Label("repositoriesMessage", message)
-				.setEscapeModelStrings(false).setVisible(message.length() > 0);
-
-		add(repositoriesMessage);
-
-		BookmarkablePageLink<Void> helpLink = new BookmarkablePageLink<Void>("filestoreHelp", FilestoreUsage.class);
-		helpLink.add(new Label("helpMessage", getString("gb.filestoreHelp")));
-		add(helpLink);
-
-		DataView<FilestoreModel> filesView = new DataView<FilestoreModel>("fileRow",
-				new ListDataProvider<FilestoreModel>(files)) {
+		BookmarkablePageLink<Void> itemDeleted = new BookmarkablePageLink<Void>("filterByDeleted", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(prevPage, SortBy.deleted.name()));
+		
+		
+		List<FilestoreModel> filteredResults = new ArrayList<FilestoreModel>(files.size());
+		
+		if (filter == null) {
+			filteredResults = files;
+		} else if (filter.equals(SortBy.ok.name())) {
+			WicketUtils.setCssClass(itemOk, "filter-on");
+			
+			for (FilestoreModel item : files) {
+				if (item.getStatus() == Status.Available) {
+					filteredResults.add(item);
+				}
+			}
+		} else if (filter.equals(SortBy.pending.name())) {
+			WicketUtils.setCssClass(itemPending, "filter-on");
+			
+			for (FilestoreModel item : files) {
+				if (item.getStatus() == Status.Upload_Pending) {
+					filteredResults.add(item);
+				}
+			}
+		} else if (filter.equals(SortBy.inprogress.name())) {
+			WicketUtils.setCssClass(itemInprogress, "filter-on");
+			
+			for (FilestoreModel item : files) {
+				if (item.getStatus() == Status.Upload_In_Progress) {
+					filteredResults.add(item);
+				}
+			}
+		} else if (filter.equals(SortBy.error.name())) {
+			WicketUtils.setCssClass(itemError, "filter-on");
+			
+			for (FilestoreModel item : files) {
+				if (item.isInErrorState()) {
+					filteredResults.add(item);
+				}
+			}
+		} else if (filter.equals(SortBy.deleted.name())) {
+			WicketUtils.setCssClass(itemDeleted, "filter-on");
+			
+			for (FilestoreModel item : files) {
+				if (item.getStatus() == Status.Deleted) {
+					filteredResults.add(item);
+				}
+			}
+		}
+		
+		DataView<FilestoreModel> filesView = new DataView<FilestoreModel>("fileRow", 
+				new ListDataProvider<FilestoreModel>(filteredResults) , itemsPerPage) {
 			private static final long serialVersionUID = 1L;
 			private int counter;
 
@@ -106,6 +186,56 @@
 
 		};
 
+
+		if (filteredResults.size() < itemsPerPage) {
+			filesView.setCurrentPage(0);
+			hasMore = false;
+		} else {
+			filesView.setCurrentPage(pageNumber - 1);
+			hasMore = true;
+		}
+
+		
 		add(filesView);
+		
+		
+		add(new BookmarkablePageLink<Void>("firstPageBottom", FilestorePage.class).setEnabled(pageNumber > 1));
+		add(new BookmarkablePageLink<Void>("prevPageBottom", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(prevPage, filter)).setEnabled(pageNumber > 1));
+		add(new BookmarkablePageLink<Void>("nextPageBottom", FilestorePage.class,
+				WicketUtils.newFilestorePageParameter(nextPage, filter)).setEnabled(hasMore));
+		
+
+		itemOk.add(FilestoreUI.getStatusIcon("statusOkIcon", FilestoreModel.Status.Available));
+		itemPending.add(FilestoreUI.getStatusIcon("statusPendingIcon", FilestoreModel.Status.Upload_Pending));
+		itemInprogress.add(FilestoreUI.getStatusIcon("statusInprogressIcon", FilestoreModel.Status.Upload_In_Progress));
+		itemError.add(FilestoreUI.getStatusIcon("statusErrorIcon", FilestoreModel.Status.Error_Unknown));
+		itemDeleted.add(FilestoreUI.getStatusIcon("statusDeletedIcon", FilestoreModel.Status.Deleted));
+		
+		itemOk.add(new Label("statusOkCount", String.valueOf(nOk)));
+		itemPending.add(new Label("statusPendingCount", String.valueOf(nPending)));
+		itemInprogress.add(new Label("statusInprogressCount", String.valueOf(nInprogress)));
+		itemError.add(new Label("statusErrorCount", String.valueOf(nError)));
+		itemDeleted.add(new Label("statusDeletedCount", String.valueOf(nDeleted)));
+		
+		add(itemOk);
+		add(itemPending);
+		add(itemInprogress);
+		add(itemError);
+		add(itemDeleted);
+		
+		add(new Label("spaceAvailable", String.format("%s / %s",
+				FileUtils.byteCountToDisplaySize(nBytesUsed),
+				FileUtils.byteCountToDisplaySize(nBytesAvailable))));
+		
+		BookmarkablePageLink<Void> helpLink = new BookmarkablePageLink<Void>("filestoreHelp", FilestoreUsage.class);
+		helpLink.add(new Label("helpMessage", getString("gb.filestoreHelp")));
+		add(helpLink);
+
 	}
-}
+		
+	protected enum SortBy {
+		ok, pending, inprogress, error, deleted;
+	}
+	
+}
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java
index b2fd903..1d81061 100644
--- a/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/LuceneSearchPage.java
@@ -66,6 +66,8 @@
 		// default values

 		ArrayList<String> repositories = new ArrayList<String>();

 		String query = "";

+		boolean allRepos = false;

+

 		int page = 1;

 		int pageSize = app().settings().getInteger(Keys.web.itemsPerPage, 50);

 

@@ -91,8 +93,9 @@
 				List<String> list = StringUtils.getStringsFromValue(value);

 				repositories.addAll(list);

 			}

-
-			if (params.containsKey("allrepos")) {

+

+			allRepos = params.getAsBoolean("allrepos", false);
+			if (allRepos) {

 				repositories.addAll(availableRepositories);

 			}

 

@@ -133,7 +136,7 @@
 		// search form

 		final Model<String> queryModel = new Model<String>(query);

 		final Model<ArrayList<String>> repositoriesModel = new Model<ArrayList<String>>(searchRepositories);

-		final Model<Boolean> allreposModel = new Model<Boolean>(params != null && params.containsKey("allrepos"));

+		final Model<Boolean> allreposModel = new Model<Boolean>(allRepos);

 		SessionlessForm<Void> form = new SessionlessForm<Void>("searchForm", getClass()) {

 

 			private static final long serialVersionUID = 1L;

diff --git a/src/main/resources/gitblit.css b/src/main/resources/gitblit.css
index 1cae6d5..3318441 100644
--- a/src/main/resources/gitblit.css
+++ b/src/main/resources/gitblit.css
@@ -2361,6 +2361,33 @@
 	color:#815b3a;

 }

 

+.filestore-status {

+	display: inline;

+	font-size: 1.2em;

+}

+

+table.filestore-status {

+	border:none!important;

+	border-spacing: 10px 0px;

+    border-collapse: separate;

+}

+

+.filestore-status tr td a {

+	border:none!important;

+	margin-right:1.5em!important;

+	padding:0.25em;

+}

+

+.filestore-status td a:hover, .filestore-status td a.filter-on {

+	background-color: #eee;

+	border-radius:5px;

+}

+

+.filestore-status span:nth-child(2) {

+	font-weight:800;

+	margin-left:0.25em;

+}

+

 .delete-patchset {

 	color:#D51900;

 	font-size: 1.2em;