]> source.dussan.org Git - gitblit.git/commitdiff
Author and Committer search integration.
authorJames Moger <james.moger@gitblit.com>
Mon, 18 Apr 2011 20:53:23 +0000 (16:53 -0400)
committerJames Moger <james.moger@gitblit.com>
Mon, 18 Apr 2011 20:53:23 +0000 (16:53 -0400)
21 files changed:
gitblit.properties
src/com/gitblit/Constants.java
src/com/gitblit/utils/JGitUtils.java
src/com/gitblit/wicket/GitBlitWebApp.java
src/com/gitblit/wicket/GitBlitWebApp.properties
src/com/gitblit/wicket/RepositoryPage.java
src/com/gitblit/wicket/WicketUtils.java
src/com/gitblit/wicket/pages/CommitPage.html
src/com/gitblit/wicket/pages/CommitPage.java
src/com/gitblit/wicket/pages/SearchPage.html [new file with mode: 0644]
src/com/gitblit/wicket/pages/SearchPage.java [new file with mode: 0644]
src/com/gitblit/wicket/pages/TagPage.html
src/com/gitblit/wicket/pages/TagPage.java
src/com/gitblit/wicket/panels/BasePanel.java
src/com/gitblit/wicket/panels/HistoryPanel.java
src/com/gitblit/wicket/panels/LogPanel.java
src/com/gitblit/wicket/panels/SearchPanel.html [new file with mode: 0644]
src/com/gitblit/wicket/panels/SearchPanel.java [new file with mode: 0644]
src/com/gitblit/wicket/panels/TagsPanel.html
src/com/gitblit/wicket/panels/TagsPanel.java
src/com/gitblit/wicket/resources/gitblit.css

index 93183eb7ae6b73059cf3cab7fb190bf513141f9a..ecefedfbc1b8e97128394e77adf6d4e8f7998e30 100644 (file)
@@ -48,7 +48,7 @@ web.allowAdministration = true
 \r
 # This is the message display above the repositories table.\r
 # This can point to a file with HTML content.\r
-web.repositoriesMessage = Welcome to Git:Blit!<br>A quick and easy way to host your own Git repositories.<br>Built with <a href="http://eclipse.org/jgit">JGit</a>, <a href="http://wicket.apache.org">Wicket</a>, <a href="http://code.google.com/p/google-code-prettify/">google-code-prettify</a>, <a href="http://eclipse.org/jetty">Jetty</a>, <a href="http://www.slf4j.org">SLF4J</a>, <a href="http://logging.apache.org/log4j">Log4j</a>, and <a href="http://jcommander.org">JCommander</a>.\r
+web.repositoriesMessage = Welcome to Git:Blit!<br>A quick and easy way to host your own Git repositories.<br>Built with <a href="http://eclipse.org/jgit">JGit</a>, <a href="http://wicket.apache.org">Wicket</a>, <a href="http://eclipse.org/jetty">Jetty</a>, <a href="http://www.slf4j.org">SLF4J</a>, <a href="http://logging.apache.org/log4j">Log4j</a>, <a href="http://code.google.com/p/google-code-prettify/">google-code-prettify</a>, and <a href="http://jcommander.org">JCommander</a>.\r
 \r
 # Use the client timezone when formatting dates.\r
 # This uses AJAX to determine the browser's timezone and enables Wicket \r
index 75f1badbd7370ae5dcba870eae9cc1c2840402f2..d5fc1a41f2d3e671e46d980ca34efd8d2f188836 100644 (file)
@@ -4,7 +4,7 @@ public class Constants {
 \r
        public final static String NAME = "Git:Blit";\r
 \r
-       public final static String VERSION = "0.0.1";\r
+       public final static String VERSION = "0.1.0-SNAPSHOT";\r
 \r
        public final static String ADMIN_ROLE = "admin";\r
 \r
index 5590ffed3012147fc13070cedb6d6e7c57723dfb..3b69c2258449c90ccd5683b3434b8a3a43a5d715 100644 (file)
@@ -20,6 +20,9 @@ import org.eclipse.jgit.diff.DiffEntry;
 import org.eclipse.jgit.diff.DiffFormatter;\r
 import org.eclipse.jgit.diff.RawTextComparator;\r
 import org.eclipse.jgit.errors.ConfigInvalidException;\r
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;\r
+import org.eclipse.jgit.errors.MissingObjectException;\r
+import org.eclipse.jgit.errors.StopWalkException;\r
 import org.eclipse.jgit.lib.AnyObjectId;\r
 import org.eclipse.jgit.lib.Constants;\r
 import org.eclipse.jgit.lib.FileMode;\r
@@ -34,6 +37,7 @@ import org.eclipse.jgit.revwalk.RevCommit;
 import org.eclipse.jgit.revwalk.RevObject;\r
 import org.eclipse.jgit.revwalk.RevTree;\r
 import org.eclipse.jgit.revwalk.RevWalk;\r
+import org.eclipse.jgit.revwalk.filter.RevFilter;\r
 import org.eclipse.jgit.treewalk.TreeWalk;\r
 import org.eclipse.jgit.treewalk.filter.AndTreeFilter;\r
 import org.eclipse.jgit.treewalk.filter.PathFilter;\r
@@ -306,7 +310,7 @@ public class JGitUtils {
                                final RevWalk rw = new RevWalk(r);\r
                                RevCommit parent = rw.parseCommit(commit.getParent(0).getId());\r
                                rw.dispose();\r
-                               baseTree = parent.getTree();    \r
+                               baseTree = parent.getTree();\r
                        } else {\r
                                baseTree = baseCommit.getTree();\r
                        }\r
@@ -364,7 +368,7 @@ public class JGitUtils {
        public static String getCommitPatch(Repository r, RevCommit commit, String path) {\r
                return getCommitPatch(r, null, commit, path);\r
        }\r
-       \r
+\r
        public static String getCommitPatch(Repository r, RevCommit baseCommit, RevCommit commit, String path) {\r
                try {\r
                        RevTree baseTree;\r
@@ -463,7 +467,7 @@ public class JGitUtils {
        public static List<RevCommit> getRevLog(Repository r, String objectId, int offset, int maxCount) {\r
                return getRevLog(r, objectId, null, offset, maxCount);\r
        }\r
-       \r
+\r
        public static List<RevCommit> getRevLog(Repository r, String objectId, String path, int offset, int maxCount) {\r
                List<RevCommit> list = new ArrayList<RevCommit>();\r
                try {\r
@@ -474,9 +478,7 @@ public class JGitUtils {
                        ObjectId object = r.resolve(objectId);\r
                        walk.markStart(walk.parseCommit(object));\r
                        if (!StringUtils.isEmpty(path)) {\r
-                               TreeFilter filter = AndTreeFilter.create(PathFilterGroup\r
-                                               .createFromStrings(Collections.singleton(path)),\r
-                                               TreeFilter.ANY_DIFF);\r
+                               TreeFilter filter = AndTreeFilter.create(PathFilterGroup.createFromStrings(Collections.singleton(path)), TreeFilter.ANY_DIFF);\r
                                walk.setTreeFilter(filter);\r
                        }\r
                        Iterable<RevCommit> revlog = walk;\r
@@ -506,6 +508,77 @@ public class JGitUtils {
                return list;\r
        }\r
 \r
+       public static enum SearchType {\r
+               AUTHOR, COMMITTER, COMMIT;\r
+\r
+               public static SearchType forName(String name) {\r
+                       for (SearchType type : values()) {\r
+                               if (type.name().equalsIgnoreCase(name)) {\r
+                                       return type;\r
+                               }\r
+                       }\r
+                       return null;\r
+               }\r
+       }\r
+\r
+       public static List<RevCommit> searchRevlogs(Repository r, String objectId, String value, final SearchType type, int offset, int maxCount) {\r
+               final String lcValue = value.toLowerCase();\r
+               List<RevCommit> list = new ArrayList<RevCommit>();\r
+               try {\r
+                       if (objectId == null || objectId.trim().length() == 0) {\r
+                               objectId = Constants.HEAD;\r
+                       }\r
+                       RevWalk walk = new RevWalk(r);\r
+                       walk.setRevFilter(new RevFilter() {\r
+\r
+                               @Override\r
+                               public RevFilter clone() {\r
+                                       return this;\r
+                               }\r
+\r
+                               @Override\r
+                               public boolean include(RevWalk walker, RevCommit commit) throws StopWalkException, MissingObjectException, IncorrectObjectTypeException, IOException {\r
+                                       switch (type) {\r
+                                       case AUTHOR:\r
+                                               return (commit.getAuthorIdent().getName().toLowerCase().indexOf(lcValue) > -1) || (commit.getAuthorIdent().getEmailAddress().toLowerCase().indexOf(lcValue) > -1);\r
+                                       case COMMITTER:\r
+                                               return (commit.getCommitterIdent().getName().toLowerCase().indexOf(lcValue) > -1)|| (commit.getCommitterIdent().getEmailAddress().toLowerCase().indexOf(lcValue) > -1);\r
+                                       case COMMIT:\r
+                                               return commit.getFullMessage().toLowerCase().indexOf(lcValue) > -1;\r
+                                       }\r
+                                       return false;\r
+                               }\r
+\r
+                       });\r
+                       ObjectId object = r.resolve(objectId);\r
+                       walk.markStart(walk.parseCommit(object));\r
+                       Iterable<RevCommit> revlog = walk;\r
+                       if (offset > 0) {\r
+                               int count = 0;\r
+                               for (RevCommit rev : revlog) {\r
+                                       count++;\r
+                                       if (count > offset) {\r
+                                               list.add(rev);\r
+                                               if (maxCount > 0 && list.size() == maxCount) {\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       } else {\r
+                               for (RevCommit rev : revlog) {\r
+                                       list.add(rev);\r
+                                       if (maxCount > 0 && list.size() == maxCount) {\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+                       walk.dispose();\r
+               } catch (Throwable t) {\r
+                       LOGGER.error("Failed to determine last change", t);\r
+               }\r
+               return list;\r
+       }\r
+\r
        public static List<RefModel> getTags(Repository r, int maxCount) {\r
                return getRefs(r, Constants.R_TAGS, maxCount);\r
        }\r
index 74057c99d7e57761445ab0d8f1623869e12111fe..dc1e2c9ce1ef3186af85dc97a1322fbe657c558e 100644 (file)
@@ -22,11 +22,12 @@ import com.gitblit.wicket.pages.LogPage;
 import com.gitblit.wicket.pages.PatchPage;\r
 import com.gitblit.wicket.pages.RawPage;\r
 import com.gitblit.wicket.pages.RepositoriesPage;\r
+import com.gitblit.wicket.pages.SearchPage;\r
 import com.gitblit.wicket.pages.SummaryPage;\r
 import com.gitblit.wicket.pages.TagPage;\r
 import com.gitblit.wicket.pages.TagsPage;\r
-import com.gitblit.wicket.pages.TicketsPage;\r
 import com.gitblit.wicket.pages.TicketPage;\r
+import com.gitblit.wicket.pages.TicketsPage;\r
 import com.gitblit.wicket.pages.TreePage;\r
 \r
 public class GitBlitWebApp extends WebApplication {\r
@@ -62,6 +63,7 @@ public class GitBlitWebApp extends WebApplication {
                mount(new MixedParamUrlCodingStrategy("/commitdiff", CommitDiffPage.class, new String[] { "r", "h" }));\r
                mount(new MixedParamUrlCodingStrategy("/patch", PatchPage.class, new String[] { "r", "h", "f" }));\r
                mount(new MixedParamUrlCodingStrategy("/history", HistoryPage.class, new String[] { "r", "h", "f" }));\r
+               mount(new MixedParamUrlCodingStrategy("/search", SearchPage.class, new String[] { "r", "h", "a", "c" }));\r
 \r
                // setup ticket urls\r
                mount(new MixedParamUrlCodingStrategy("/tickets", TicketsPage.class, new String[] { "r" }));\r
index 331fc2940cc340e1503e3c0620e4330e64d1e5ce..ca757768b6c1c3634b7a73b1da5694333ac78027 100644 (file)
@@ -47,4 +47,7 @@ gb.username = Username
 gb.password = Password\r
 gb.tagger = tagger\r
 gb.moreHistory = more history...\r
-gb.difftocurrent = diff to current
\ No newline at end of file
+gb.difftocurrent = diff to current\r
+gb.search = search\r
+gb.searchForAuthor = Search for commits authored by\r
+gb.searchForCommitter = Search for commits committed by
\ No newline at end of file
index 7378543f5ba1f7798d6f42410af2541bbec4c414..6442bee8df416f8adfbbb859e571de3aaaf8a3c9 100644 (file)
@@ -6,9 +6,12 @@ import java.util.Map;
 \r
 import javax.servlet.http.HttpServletRequest;\r
 \r
+import org.apache.wicket.Component;\r
 import org.apache.wicket.PageParameters;\r
 import org.apache.wicket.markup.html.basic.Label;\r
+import org.apache.wicket.markup.html.panel.Fragment;\r
 import org.apache.wicket.protocol.http.servlet.ServletWebRequest;\r
+import org.eclipse.jgit.lib.PersonIdent;\r
 import org.eclipse.jgit.lib.Repository;\r
 import org.eclipse.jgit.revwalk.RevCommit;\r
 import org.slf4j.Logger;\r
@@ -18,7 +21,9 @@ import com.gitblit.GitBlit;
 import com.gitblit.Keys;\r
 import com.gitblit.utils.JGitUtils;\r
 import com.gitblit.utils.StringUtils;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.wicket.pages.RepositoriesPage;\r
+import com.gitblit.wicket.pages.SearchPage;\r
 import com.gitblit.wicket.panels.PageLinksPanel;\r
 import com.gitblit.wicket.panels.RefsPanel;\r
 \r
@@ -109,6 +114,38 @@ public abstract class RepositoryPage extends BasePage {
 \r
        protected abstract String getPageName();\r
 \r
+       \r
+       protected Component createPersonPanel(String wicketId, PersonIdent identity, SearchType searchType) {\r
+               if (StringUtils.isEmpty(identity.getName()) || StringUtils.isEmpty(identity.getEmailAddress())) {\r
+                       String value = identity.getName();\r
+                       if (StringUtils.isEmpty(value)) {\r
+                               value = identity.getEmailAddress();\r
+                       }\r
+                       Fragment partial = new Fragment(wicketId, "partialPersonIdent", this);\r
+                       LinkPanel link = new LinkPanel("personName", "list", value, SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType));\r
+                       setPersonSearchTooltip(link, value, searchType);\r
+                       partial.add(link);\r
+                       return partial;\r
+               } else {\r
+                       Fragment fullPerson = new Fragment(wicketId, "fullPersonIdent", this);\r
+                       LinkPanel nameLink = new LinkPanel("personName", "list", identity.getName(), SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, identity.getName(), searchType));\r
+                       setPersonSearchTooltip(nameLink, identity.getName(), searchType);\r
+                       fullPerson.add(nameLink);\r
+                       \r
+                       LinkPanel addressLink = new LinkPanel("personAddress", "list", "<" + identity.getEmailAddress() + ">", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, identity.getEmailAddress(), searchType));\r
+                       setPersonSearchTooltip(addressLink, identity.getEmailAddress(), searchType);\r
+                       fullPerson.add(addressLink);\r
+                       return fullPerson;\r
+               }\r
+       }\r
+       \r
+       protected void setPersonSearchTooltip(Component component, String value, SearchType searchType) {\r
+               if (searchType.equals(SearchType.AUTHOR)) {\r
+                       WicketUtils.setHtmlTitle(component, getString("gb.searchForAuthor") + " " + value);\r
+               } else if (searchType.equals(SearchType.COMMITTER)) {\r
+                       WicketUtils.setHtmlTitle(component, getString("gb.searchForCommitter") + " " + value);\r
+               }\r
+       }\r
        @Override\r
        protected void onBeforeRender() {\r
                // dispose of repository object\r
index 0a1c3a03f9afd80b44913c51f282e87486dca6ca..e47432578db5e44301deb9d570a577cfd0128799 100644 (file)
@@ -13,6 +13,7 @@ import org.eclipse.jgit.lib.Constants;
 \r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.utils.TimeUtils;\r
 \r
@@ -81,7 +82,7 @@ public class WicketUtils {
                }\r
                return new PageParameters("r=" + repositoryName + ",h=" + objectId + ",page=" + pageNumber);\r
        }\r
-       \r
+\r
        public static PageParameters newHistoryPageParameter(String repositoryName, String objectId, String path, int pageNumber) {\r
                if (pageNumber <= 1) {\r
                        return newObjectParameter(repositoryName, objectId);\r
@@ -93,7 +94,17 @@ public class WicketUtils {
                return new PageParameters("r=" + repositoryName + ",h=" + commitId + ",f=" + path + ",hb=" + baseCommitId);\r
        }\r
 \r
-       \r
+       public static PageParameters newSearchParameter(String repositoryName, String commitId, String search, SearchType type) {\r
+               if (StringUtils.isEmpty(commitId)) {\r
+                       return new PageParameters("r=" + repositoryName + ",s=" + search + ",st=" + type.name());       \r
+               }\r
+               return new PageParameters("r=" + repositoryName + ",h=" + commitId + ",s=" + search + ",st=" + type.name());\r
+       }\r
+\r
+       public static PageParameters newSearchParameter(String repositoryName, String commitId, String search, SearchType type, int pageNumber) {\r
+               return new PageParameters("r=" + repositoryName + ",h=" + commitId + ",s=" + search + ",st=" + type.name() + ",page=" + pageNumber);\r
+       }\r
+\r
        public static String getRepositoryName(PageParameters params) {\r
                return params.getString("r", "");\r
        }\r
@@ -105,11 +116,19 @@ public class WicketUtils {
        public static String getPath(PageParameters params) {\r
                return params.getString("f", null);\r
        }\r
-       \r
+\r
        public static String getBaseObjectId(PageParameters params) {\r
                return params.getString("hb", null);\r
        }\r
 \r
+       public static String getSearchString(PageParameters params) {\r
+               return params.getString("s", null);\r
+       }\r
+\r
+       public static String getSearchType(PageParameters params) {\r
+               return params.getString("st", null);\r
+       }\r
+\r
        public static int getPage(PageParameters params) {\r
                return params.getInt("page", 1); // index from 1\r
        }\r
index 8d06fc19f237a748a21c758b29c502bf0266a972..ec1b55df6a7a773873470732637db19fcc1a0948 100644 (file)
        <!-- commit info -->\r
        <table class="plain">\r
                <tr><th><wicket:message key="gb.refs">refs</wicket:message></th><td><div wicket:id="refsPanel">[references]</div></td></tr>\r
-               <tr><th><wicket:message key="gb.author">author</wicket:message></th><td><span wicket:id="commitAuthor">[author</span></td></tr>\r
-               <tr><th></th><td><span wicket:id="commitAuthorDate">[author date]</span></td></tr>\r
-               <tr><th><wicket:message key="gb.committer">committer</wicket:message></th><td><span wicket:id="commitCommitter">[committer]</span></td></tr>\r
-               <tr><th></th><td><span wicket:id="commitCommitterDate">[commit date]</span></td></tr>\r
+               <tr><th><wicket:message key="gb.author">author</wicket:message></th><td><span class="sha1" wicket:id="commitAuthor">[author</span></td></tr>\r
+               <tr><th></th><td><span class="sha1" wicket:id="commitAuthorDate">[author date]</span></td></tr>\r
+               <tr><th><wicket:message key="gb.committer">committer</wicket:message></th><td><span class="sha1" wicket:id="commitCommitter">[committer]</span></td></tr>\r
+               <tr><th></th><td><span class="sha1" wicket:id="commitCommitterDate">[commit date]</span></td></tr>\r
                <tr><th><wicket:message key="gb.commit">commit</wicket:message></th><td><span class="sha1" wicket:id="commitId">[commit id]</span></td></tr>\r
                <tr><th><wicket:message key="gb.tree">tree</wicket:message></th><td><span class="sha1" wicket:id="commitTree">[commit tree]</span></td></tr>\r
                <tr><th valign="top"><wicket:message key="gb.parent">parent</wicket:message></th>\r
                </tr>\r
        </table>\r
        \r
+       <wicket:fragment wicket:id="fullPersonIdent">\r
+               <span wicket:id="personName"></span><span wicket:id="personAddress"></span>\r
+       </wicket:fragment>\r
+       \r
+       <wicket:fragment wicket:id="partialPersonIdent">\r
+               <span wicket:id="personName"></span>\r
+       </wicket:fragment>\r
+       \r
 </wicket:extend>\r
 </body>\r
 </html>
\ No newline at end of file
index 63817ca39d29acbad7a42c42b7695d63f61c335d..064a7fe529a8ba992e6eb2acc46024fe3e4e281a 100644 (file)
@@ -14,6 +14,7 @@ import org.eclipse.jgit.lib.Repository;
 import org.eclipse.jgit.revwalk.RevCommit;\r
 \r
 import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.wicket.LinkPanel;\r
 import com.gitblit.wicket.RepositoryPage;\r
 import com.gitblit.wicket.WicketUtils;\r
@@ -48,10 +49,12 @@ public class CommitPage extends RepositoryPage {
 \r
                addRefs(r, c);\r
 \r
-               add(new Label("commitAuthor", JGitUtils.getDisplayName(c.getAuthorIdent())));\r
+               // author\r
+               add(createPersonPanel("commitAuthor", c.getAuthorIdent(), SearchType.AUTHOR));\r
                add(WicketUtils.createTimestampLabel("commitAuthorDate", c.getAuthorIdent().getWhen(), getTimeZone()));\r
 \r
-               add(new Label("commitCommitter", JGitUtils.getDisplayName(c.getCommitterIdent())));\r
+               // committer\r
+               add(createPersonPanel("commitCommitter", c.getCommitterIdent(), SearchType.COMMITTER));         \r
                add(WicketUtils.createTimestampLabel("commitCommitterDate", c.getCommitterIdent().getWhen(), getTimeZone()));\r
 \r
                add(new Label("commitId", c.getName()));\r
@@ -100,7 +103,7 @@ public class CommitPage extends RepositoryPage {
                };\r
                add(pathsView);\r
        }\r
-\r
+       \r
        @Override\r
        protected String getPageName() {\r
                return getString("gb.commit");\r
diff --git a/src/com/gitblit/wicket/pages/SearchPage.html b/src/com/gitblit/wicket/pages/SearchPage.html
new file mode 100644 (file)
index 0000000..7d2a537
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml"  \r
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
+      xml:lang="en"  \r
+      lang="en"> \r
+\r
+<body>\r
+<wicket:extend>\r
+\r
+       <!-- page nav links --> \r
+       <div wicket:id="pageLinks">[page links]</div>\r
+\r
+       <!-- pager links -->\r
+       <div style="padding-top:5px;padding-bottom:5px;">\r
+               <a wicket:id="firstPageTop"><wicket:message key="gb.pageFirst"></wicket:message></a> | <a wicket:id="prevPageTop"><wicket:message key="gb.pagePrevious"></wicket:message></a> | <a wicket:id="nextPageTop"><wicket:message key="gb.pageNext"></wicket:message></a> \r
+       </div>\r
+       \r
+       <!-- history -->\r
+       <div style="margin-top:5px;" wicket:id="searchPanel">[search panel]</div>\r
+\r
+       <!-- pager links -->\r
+       <div style="padding-bottom:5px;">\r
+               <a wicket:id="firstPageBottom"><wicket:message key="gb.pageFirst"></wicket:message></a> | <a wicket:id="prevPageBottom"><wicket:message key="gb.pagePrevious"></wicket:message></a> | <a wicket:id="nextPageBottom"><wicket:message key="gb.pageNext"></wicket:message></a> \r
+       </div>\r
+\r
+</wicket:extend>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/SearchPage.java b/src/com/gitblit/wicket/pages/SearchPage.java
new file mode 100644 (file)
index 0000000..d0f12c2
--- /dev/null
@@ -0,0 +1,42 @@
+package com.gitblit.wicket.pages;\r
+\r
+import org.apache.wicket.PageParameters;\r
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
+\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
+import com.gitblit.wicket.RepositoryPage;\r
+import com.gitblit.wicket.WicketUtils;\r
+import com.gitblit.wicket.panels.SearchPanel;\r
+\r
+public class SearchPage extends RepositoryPage {\r
+       \r
+       public SearchPage(PageParameters params) {\r
+               super(params);\r
+\r
+               String value = WicketUtils.getSearchString(params);\r
+               String type = WicketUtils.getSearchType(params);\r
+               SearchType searchType = SearchType.forName(type);\r
+               \r
+               int pageNumber = WicketUtils.getPage(params);\r
+               int prevPage = Math.max(0, pageNumber - 1);\r
+               int nextPage = pageNumber + 1;\r
+\r
+               SearchPanel search = new SearchPanel("searchPanel", repositoryName, objectId, value, searchType, getRepository(), -1, pageNumber - 1);\r
+               boolean hasMore = search.hasMore();\r
+               add(search);\r
+\r
+               add(new BookmarkablePageLink<Void>("firstPageTop", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType)).setEnabled(pageNumber > 1));\r
+               add(new BookmarkablePageLink<Void>("prevPageTop", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType, prevPage)).setEnabled(pageNumber > 1));\r
+               add(new BookmarkablePageLink<Void>("nextPageTop", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType, nextPage)).setEnabled(hasMore));\r
+\r
+               add(new BookmarkablePageLink<Void>("firstPageBottom", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType)).setEnabled(pageNumber > 1));\r
+               add(new BookmarkablePageLink<Void>("prevPageBottom", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType, prevPage)).setEnabled(pageNumber > 1));\r
+               add(new BookmarkablePageLink<Void>("nextPageBottom", SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, value, searchType, nextPage)).setEnabled(hasMore));\r
+\r
+       }\r
+\r
+       @Override\r
+       protected String getPageName() {\r
+               return getString("gb.search");\r
+       }\r
+}\r
index cd2e19b73185caa8e3b9061464a72e7a98ec824f..e41046283091c124a745e3b2f05cc4c98bb1ac9d 100644 (file)
        <!-- commit info -->\r
        <table class="plain">\r
                <tr><th><wicket:message key="gb.object">[object]</wicket:message></th><td><span class="sha1" wicket:id="tagId">[tag id]</span></td></tr>\r
-               <tr><th><wicket:message key="gb.tagger">[tagger]</wicket:message></th><td><span wicket:id="tagAuthor">[tag author]</span></td></tr>\r
-               <tr><th></th><td><span wicket:id="tagDate">[tag date]</span></td></tr>\r
+               <tr><th><wicket:message key="gb.tagger">[tagger]</wicket:message></th><td><span class="sha1" wicket:id="tagAuthor">[tag author]</span></td></tr>\r
+               <tr><th></th><td><span class="sha1" wicket:id="tagDate">[tag date]</span></td></tr>\r
        </table>\r
        \r
        <!--  full message -->\r
        <div style="border-bottom:0px;" class="commit_message" wicket:id="fullMessage">[tag full message]</div>\r
        \r
+       <wicket:fragment wicket:id="fullPersonIdent">\r
+               <span wicket:id="personName"></span><span wicket:id="personAddress"></span>\r
+       </wicket:fragment>\r
+       \r
+       <wicket:fragment wicket:id="partialPersonIdent">\r
+               <span wicket:id="personName"></span>\r
+       </wicket:fragment>\r
+       \r
 </wicket:extend>\r
 </body>\r
 </html>
\ No newline at end of file
index d36c887a4f20a26415ff7384ceaa2861cd5841d4..7448ae5d190fff306d574bba748cd86add93e81a 100644 (file)
@@ -3,11 +3,11 @@ package com.gitblit.wicket.pages;
 import java.util.List;\r
 \r
 import org.apache.wicket.PageParameters;\r
-import org.apache.wicket.markup.html.basic.Label;\r
 import org.eclipse.jgit.lib.Repository;\r
 import org.eclipse.jgit.revwalk.RevCommit;\r
 \r
 import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.wicket.LinkPanel;\r
 import com.gitblit.wicket.RepositoryPage;\r
 import com.gitblit.wicket.WicketUtils;\r
@@ -41,7 +41,7 @@ public class TagPage extends RepositoryPage {
                        add(new LinkPanel("tagId", "list", c.getName(), CommitPage.class, newCommitParameter(c.getName())));\r
                }\r
 \r
-               add(new Label("tagAuthor", JGitUtils.getDisplayName(c.getAuthorIdent())));\r
+               add(createPersonPanel("tagAuthor", c.getAuthorIdent(), SearchType.AUTHOR));\r
                add(WicketUtils.createTimestampLabel("tagDate", c.getAuthorIdent().getWhen(), getTimeZone()));\r
 \r
                addFullText("fullMessage", c.getFullMessage(), true);\r
index 6ddc0a072cf67b91dc9b279637d0ce9dc22f9742..8a168ab4edb09d50189a5485927c6c6e70a36ee2 100644 (file)
@@ -2,11 +2,14 @@ package com.gitblit.wicket.panels;
 \r
 import java.util.TimeZone;\r
 \r
+import org.apache.wicket.Component;\r
 import org.apache.wicket.markup.html.panel.Panel;\r
 \r
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.wicket.GitBlitWebSession;\r
+import com.gitblit.wicket.WicketUtils;\r
 \r
 public abstract class BasePanel extends Panel {\r
 \r
@@ -19,4 +22,12 @@ public abstract class BasePanel extends Panel {
        protected TimeZone getTimeZone() {\r
                return GitBlit.self().settings().getBoolean(Keys.web.useClientTimezone, false) ? GitBlitWebSession.get().getTimezone() : TimeZone.getDefault();\r
        }\r
+\r
+       protected void setPersonSearchTooltip(Component component, String value, SearchType searchType) {\r
+               if (searchType.equals(SearchType.AUTHOR)) {\r
+                       WicketUtils.setHtmlTitle(component, getString("gb.searchForAuthor") + " " + value);\r
+               } else if (searchType.equals(SearchType.COMMITTER)) {\r
+                       WicketUtils.setHtmlTitle(component, getString("gb.searchForCommitter") + " " + value);\r
+               }\r
+       }\r
 }\r
index 00f4d53364640036a661d1111483831a1707cb95..dd1395a700766f8693b083417e88d3141310fba8 100644 (file)
@@ -19,6 +19,7 @@ import com.gitblit.GitBlit;
 import com.gitblit.Keys;\r
 import com.gitblit.utils.JGitUtils;\r
 import com.gitblit.utils.StringUtils;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.wicket.LinkPanel;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.models.PathModel;\r
@@ -28,6 +29,7 @@ import com.gitblit.wicket.pages.CommitDiffPage;
 import com.gitblit.wicket.pages.CommitPage;\r
 import com.gitblit.wicket.pages.HistoryPage;\r
 import com.gitblit.wicket.pages.LogPage;\r
+import com.gitblit.wicket.pages.SearchPage;\r
 import com.gitblit.wicket.pages.TreePage;\r
 \r
 public class HistoryPanel extends BasePanel {\r
@@ -95,9 +97,12 @@ public class HistoryPanel extends BasePanel {
 \r
                                item.add(WicketUtils.createDateLabel("commitDate", date, getTimeZone()));\r
 \r
+                               // author search link\r
                                String author = entry.getAuthorIdent().getName();\r
-                               item.add(WicketUtils.createAuthorLabel("commitAuthor", author));\r
-\r
+                               LinkPanel authorLink = new LinkPanel("commitAuthor", "list", author, SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, author, SearchType.AUTHOR));\r
+                               setPersonSearchTooltip(authorLink, author, SearchType.AUTHOR);\r
+                               item.add(authorLink);\r
+                               \r
                                String shortMessage = entry.getShortMessage();\r
                                String trimmedMessage = StringUtils.trimShortLog(shortMessage);\r
                                LinkPanel shortlog = new LinkPanel("commitShortMessage", "list subject", trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName()));\r
index 954af757fb119ad4628cc3ff42f8138cb47d7520..04575115762cdc04d6d544dc7cdbda3829ae9732 100644 (file)
@@ -17,12 +17,14 @@ import org.eclipse.jgit.revwalk.RevCommit;
 import com.gitblit.GitBlit;\r
 import com.gitblit.Keys;\r
 import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
 import com.gitblit.utils.StringUtils;\r
 import com.gitblit.wicket.LinkPanel;\r
 import com.gitblit.wicket.WicketUtils;\r
 import com.gitblit.wicket.pages.CommitDiffPage;\r
 import com.gitblit.wicket.pages.CommitPage;\r
 import com.gitblit.wicket.pages.LogPage;\r
+import com.gitblit.wicket.pages.SearchPage;\r
 import com.gitblit.wicket.pages.SummaryPage;\r
 import com.gitblit.wicket.pages.TreePage;\r
 \r
@@ -32,7 +34,7 @@ public class LogPanel extends BasePanel {
        \r
        private boolean hasMore = false;\r
 \r
-       public LogPanel(String wicketId, final String repositoryName, String objectId, Repository r, int limit, int pageOffset) {\r
+       public LogPanel(String wicketId, final String repositoryName, final String objectId, Repository r, int limit, int pageOffset) {\r
                super(wicketId);\r
                boolean pageResults = limit <= 0;\r
                int itemsPerPage = GitBlit.self().settings().getInteger(Keys.web.logPageCommitCount, 50);\r
@@ -76,8 +78,11 @@ public class LogPanel extends BasePanel {
 \r
                                item.add(WicketUtils.createDateLabel("commitDate", date, getTimeZone()));\r
 \r
+                               // author search link\r
                                String author = entry.getAuthorIdent().getName();\r
-                               item.add(WicketUtils.createAuthorLabel("commitAuthor", author));\r
+                               LinkPanel authorLink = new LinkPanel("commitAuthor", "list", author, SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, author, SearchType.AUTHOR));\r
+                               setPersonSearchTooltip(authorLink, author, SearchType.AUTHOR);\r
+                               item.add(authorLink);\r
 \r
                                String shortMessage = entry.getShortMessage();\r
                                String trimmedMessage = StringUtils.trimShortLog(shortMessage);\r
diff --git a/src/com/gitblit/wicket/panels/SearchPanel.html b/src/com/gitblit/wicket/panels/SearchPanel.html
new file mode 100644 (file)
index 0000000..e5b28da
--- /dev/null
@@ -0,0 +1,31 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\r
+<html xmlns="http://www.w3.org/1999/xhtml"  \r
+      xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"  \r
+      xml:lang="en"  \r
+      lang="en"> \r
+\r
+<body>\r
+<wicket:panel>\r
+\r
+       <!-- header --> \r
+       <div class="header" wicket:id="header">[search header]</div>\r
+\r
+       <table style="width:100%" class="pretty">\r
+               <tbody>\r
+                       <tr wicket:id="commit">\r
+                       <td class="date"><span wicket:id="commitDate">[commit date]</span></td>\r
+                       <td class="author"><span wicket:id="commitAuthor">[commit author]</span></td>\r
+                       <td><div wicket:id="commitShortMessage">[commit short message]</div></td>\r
+                       <td class="rightAlign"><div wicket:id="commitRefs">[commit refs]</div></td>                     \r
+                       <td class="rightAlign">\r
+                               <span class="link">\r
+                                               <a wicket:id="commit"><wicket:message key="gb.commit"></wicket:message></a> | <a wicket:id="commitdiff"><wicket:message key="gb.commitdiff"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a>\r
+                                       </span>\r
+                               </td>\r
+                       </tr>\r
+       </tbody>\r
+       </table>        \r
+       \r
+</wicket:panel>\r
+</body>\r
+</html>
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/panels/SearchPanel.java b/src/com/gitblit/wicket/panels/SearchPanel.java
new file mode 100644 (file)
index 0000000..6f4858b
--- /dev/null
@@ -0,0 +1,102 @@
+package com.gitblit.wicket.panels;\r
+\r
+import java.util.Date;\r
+import java.util.List;\r
+import java.util.Map;\r
+\r
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
+import org.apache.wicket.markup.repeater.Item;\r
+import org.apache.wicket.markup.repeater.data.DataView;\r
+import org.apache.wicket.markup.repeater.data.ListDataProvider;\r
+import org.eclipse.jgit.lib.ObjectId;\r
+import org.eclipse.jgit.lib.Repository;\r
+import org.eclipse.jgit.revwalk.RevCommit;\r
+\r
+import com.gitblit.GitBlit;\r
+import com.gitblit.Keys;\r
+import com.gitblit.utils.JGitUtils;\r
+import com.gitblit.utils.StringUtils;\r
+import com.gitblit.utils.JGitUtils.SearchType;\r
+import com.gitblit.wicket.LinkPanel;\r
+import com.gitblit.wicket.WicketUtils;\r
+import com.gitblit.wicket.pages.CommitDiffPage;\r
+import com.gitblit.wicket.pages.CommitPage;\r
+import com.gitblit.wicket.pages.SearchPage;\r
+import com.gitblit.wicket.pages.TreePage;\r
+\r
+public class SearchPanel extends BasePanel {\r
+\r
+       private static final long serialVersionUID = 1L;\r
+\r
+       private boolean hasMore = false;\r
+\r
+       public SearchPanel(String wicketId, final String repositoryName, final String objectId, final String value, SearchType searchType, Repository r, int limit, int pageOffset) {\r
+               super(wicketId);\r
+               boolean pageResults = limit <= 0;\r
+               int itemsPerPage = GitBlit.self().settings().getInteger(Keys.web.logPageCommitCount, 50);\r
+               if (itemsPerPage <= 1) {\r
+                       itemsPerPage = 50;\r
+               }\r
+\r
+               RevCommit commit = JGitUtils.getCommit(r, objectId);\r
+\r
+               final Map<ObjectId, List<String>> allRefs = JGitUtils.getAllRefs(r);\r
+               List<RevCommit> commits;\r
+               if (pageResults) {\r
+                       // Paging result set\r
+                       commits = JGitUtils.searchRevlogs(r, objectId, value, searchType, pageOffset * itemsPerPage, itemsPerPage);\r
+               } else {\r
+                       // Fixed size result set\r
+                       commits = JGitUtils.searchRevlogs(r, objectId, value, searchType, 0, limit);\r
+               }\r
+\r
+               // inaccurate way to determine if there are more commits.\r
+               // works unless commits.size() represents the exact end.\r
+               hasMore = commits.size() >= itemsPerPage;\r
+\r
+               // header\r
+               add(new LinkPanel("header", "title", commit.getShortMessage(), CommitPage.class, WicketUtils.newObjectParameter(repositoryName, commit.getName())));\r
+\r
+               ListDataProvider<RevCommit> dp = new ListDataProvider<RevCommit>(commits);\r
+               DataView<RevCommit> searchView = new DataView<RevCommit>("commit", dp) {\r
+                       private static final long serialVersionUID = 1L;\r
+                       int counter = 0;\r
+\r
+                       public void populateItem(final Item<RevCommit> item) {\r
+                               final RevCommit entry = item.getModelObject();\r
+                               final Date date = JGitUtils.getCommitDate(entry);\r
+\r
+                               item.add(WicketUtils.createDateLabel("commitDate", date, getTimeZone()));\r
+\r
+                               // author search link\r
+                               String author = entry.getAuthorIdent().getName();\r
+                               LinkPanel authorLink = new LinkPanel("commitAuthor", "list", author, SearchPage.class, WicketUtils.newSearchParameter(repositoryName, objectId, author, SearchType.AUTHOR));\r
+                               setPersonSearchTooltip(authorLink, author, SearchType.AUTHOR);\r
+                               item.add(authorLink);\r
+\r
+                               String shortMessage = entry.getShortMessage();\r
+                               String trimmedMessage = StringUtils.trimShortLog(shortMessage);\r
+                               // TODO highlight matches\r
+                               LinkPanel shortlog = new LinkPanel("commitShortMessage", "list subject", trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName()));\r
+                               if (!shortMessage.equals(trimmedMessage)) {\r
+                                       WicketUtils.setHtmlTitle(shortlog, shortMessage);\r
+                               }\r
+                               item.add(shortlog);\r
+\r
+                               item.add(new RefsPanel("commitRefs", repositoryName, entry, allRefs));\r
+\r
+                               item.add(new BookmarkablePageLink<Void>("commit", CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));\r
+                               item.add(new BookmarkablePageLink<Void>("commitdiff", CommitDiffPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));\r
+                               item.add(new BookmarkablePageLink<Void>("tree", TreePage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));\r
+\r
+                               WicketUtils.setAlternatingBackground(item, counter);\r
+                               counter++;\r
+                       }\r
+               };\r
+               add(searchView);\r
+       }\r
+\r
+       public boolean hasMore() {\r
+               return hasMore;\r
+       }\r
+}\r
index 0255a7249bd3b34466685ff02dba4eafb032bc99..278b7e9b3d2869e5772ade4fd5b9fc4efecd849d 100644 (file)
@@ -16,9 +16,7 @@
                        <td><b><span wicket:id="tagName">[tag name]</span></b></td>\r
                        <td><span wicket:id="tagDescription">[tag description]</span></td>\r
                        <td class="rightAlign">\r
-                               <span class="link">\r
-                                               <a wicket:id="view"><wicket:message key="gb.view"></wicket:message></a> | <a wicket:id="commit"><wicket:message key="gb.commit"></wicket:message></a> | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a>\r
-                                       </span>\r
+                               <span wicket:id="tagLinks"></span>\r
                                </td>\r
                </tr>\r
        </tbody>\r
        \r
        <div wicket:id="allTags">[all tags]</div>       \r
 \r
+       <!--  annotated tag links -->\r
+       <wicket:fragment wicket:id="annotatedLinks">\r
+               <span class="link">\r
+                       <a wicket:id="view"><wicket:message key="gb.view"></wicket:message></a> | <a wicket:id="commit"><wicket:message key="gb.commit"></wicket:message></a> | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a>\r
+               </span>\r
+       </wicket:fragment>\r
+       \r
+       <!-- lightweight tag links -->\r
+       <wicket:fragment wicket:id="lightweightLinks">\r
+               <span class="link">\r
+                       <a wicket:id="commit"><wicket:message key="gb.commit"></wicket:message></a> | <a wicket:id="log"><wicket:message key="gb.log"></wicket:message></a>\r
+               </span>\r
+       </wicket:fragment>\r
+       \r
 </wicket:panel>\r
 </body>\r
 </html>
\ No newline at end of file
index 979a27527240d9f8418ab9e18ffdcdab74e00703..01616689c02d051018f322c8aecda9842ac66599 100644 (file)
@@ -4,6 +4,7 @@ import java.util.List;
 \r
 import org.apache.wicket.markup.html.basic.Label;\r
 import org.apache.wicket.markup.html.link.BookmarkablePageLink;\r
+import org.apache.wicket.markup.html.panel.Fragment;\r
 import org.apache.wicket.markup.repeater.Item;\r
 import org.apache.wicket.markup.repeater.data.DataView;\r
 import org.apache.wicket.markup.repeater.data.ListDataProvider;\r
@@ -58,13 +59,19 @@ public class TagsPanel extends BasePanel {
                                        message = entry.getShortLog();\r
                                }\r
                                if (entry.isAnnotatedTag()) {\r
-                                       item.add(new LinkPanel("tagDescription", "list subject", message, TagPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getObjectId().getName())));\r
+                                       item.add(new LinkPanel("tagDescription", "list", message, TagPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getObjectId().getName())));\r
+                                       Fragment fragment = new Fragment("tagLinks", "annotatedLinks", this);\r
+                                       fragment.add(new BookmarkablePageLink<Void>("view", TagPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getObjectId().getName())).setEnabled(entry.isAnnotatedTag()));\r
+                                       fragment.add(new BookmarkablePageLink<Void>("commit", CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getCommitId().getName())));\r
+                                       fragment.add(new BookmarkablePageLink<Void>("log", LogPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));\r
+                                       item.add(fragment);\r
                                } else {\r
-                                       item.add(new LinkPanel("tagDescription", "list subject", message, CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getObjectId().getName())));\r
+                                       item.add(new LinkPanel("tagDescription", "list", message, CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getObjectId().getName())));\r
+                                       Fragment fragment = new Fragment("tagLinks", "lightweightLinks", this);\r
+                                       fragment.add(new BookmarkablePageLink<Void>("commit", CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getCommitId().getName())));\r
+                                       fragment.add(new BookmarkablePageLink<Void>("log", LogPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));\r
+                                       item.add(fragment);\r
                                }\r
-                               item.add(new BookmarkablePageLink<Void>("view", TagPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getObjectId().getName())).setEnabled(entry.isAnnotatedTag()));\r
-                               item.add(new BookmarkablePageLink<Void>("commit", CommitPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getCommitId().getName())));\r
-                               item.add(new BookmarkablePageLink<Void>("log", LogPage.class, WicketUtils.newObjectParameter(repositoryName, entry.getName())));\r
 \r
                                WicketUtils.setAlternatingBackground(item, counter);\r
                                counter++;\r
index c5a416b9e617e3cc444f3af1a7051ff54aa31d59..736dbb3644d74b27c10fb27d95937af76d37546f 100644 (file)
@@ -104,7 +104,7 @@ div.page_header {
        font-family: sans-serif;\r
        font-weight: bold;\r
        font-size: 150%;\r
-       color: #bbb;\r
+       color: #888;\r
        background-color: #ffffff;\r
 }\r
 \r
@@ -129,6 +129,7 @@ div.page_header a:hover {
 }\r
 \r
 div.page_footer {\r
+       clear: both;\r
        height: 17px;\r
        color: black;\r
        background-color: #ffffff;\r
@@ -274,6 +275,14 @@ a.list {
        color: #000000;\r
 }\r
 \r
+a.list.subject {\r
+       font-weight: bold;\r
+}\r
+\r
+a.list.name {\r
+       font-weight: bold;      \r
+}\r
+\r
 a.list:hover {\r
        text-decoration: underline;\r
        color: #880000;\r