summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJames Moger <james.moger@gitblit.com>2011-05-23 16:46:09 -0400
committerJames Moger <james.moger@gitblit.com>2011-05-23 16:46:09 -0400
commita4d2498b7f94012cfdf481fcf151f8cfd7537a42 (patch)
treea5ad4a3d883d80ac76992799510544a43c7c124a
parenta9299738a991014788b72db7c9afc946633590e2 (diff)
downloadgitblit-a4d2498b7f94012cfdf481fcf151f8cfd7537a42.tar.gz
gitblit-a4d2498b7f94012cfdf481fcf151f8cfd7537a42.zip
User list. Revised home page. Updated Jetty. Secure cookies. Docs.
-rw-r--r--.classpath10
-rw-r--r--build.xml51
-rw-r--r--distrib/gitblit.properties2
-rw-r--r--docs/00_index.mkd15
-rw-r--r--docs/00_setup.mkd2
-rw-r--r--docs/01_faq.mkd16
-rw-r--r--docs/01_screenshots.mkd4
-rw-r--r--docs/screenshots/00.pngbin69136 -> 79888 bytes
-rw-r--r--docs/screenshots/raw/00.pngbin105237 -> 148301 bytes
-rw-r--r--docs/screenshots/thumbs/00.pngbin18333 -> 38921 bytes
-rw-r--r--src/com/gitblit/Build.java2
-rw-r--r--src/com/gitblit/BuildSite.java24
-rw-r--r--src/com/gitblit/Constants.java6
-rw-r--r--src/com/gitblit/GitBlitServer.java11
-rw-r--r--src/com/gitblit/wicket/GitBlitWebApp.properties4
-rw-r--r--src/com/gitblit/wicket/WicketUtils.java4
-rw-r--r--src/com/gitblit/wicket/pages/EditUserPage.html2
-rw-r--r--src/com/gitblit/wicket/pages/RepositoriesPage.html61
-rw-r--r--src/com/gitblit/wicket/pages/RepositoriesPage.java260
-rw-r--r--src/com/gitblit/wicket/panels/RepositoriesPanel.html88
-rw-r--r--src/com/gitblit/wicket/panels/RepositoriesPanel.java274
-rw-r--r--src/com/gitblit/wicket/panels/UsersPanel.html48
-rw-r--r--src/com/gitblit/wicket/panels/UsersPanel.java46
-rw-r--r--src/com/gitblit/wicket/resources/add_16x16.pngbin0 -> 698 bytes
-rw-r--r--src/com/gitblit/wicket/resources/gitblit.css54
-rw-r--r--src/com/gitblit/wicket/resources/gitweb-favicon.pngbin0 -> 164 bytes
-rw-r--r--src/com/gitblit/wicket/resources/user_16x16.pngbin0 -> 601 bytes
27 files changed, 610 insertions, 374 deletions
diff --git a/.classpath b/.classpath
index 5cddd209..4e3fa85c 100644
--- a/.classpath
+++ b/.classpath
@@ -18,11 +18,6 @@
<attribute name="javadoc_location" value="jar:platform:/resource/gitblit/ext/slf4j-log4j12-1.6.1-javadoc.jar!/"/>
</attributes>
</classpathentry>
- <classpathentry kind="lib" path="ext/jetty-all-7.2.2.v20101205.jar" sourcepath="ext/jetty-all-7.2.2.v20101205-sources.jar">
- <attributes>
- <attribute name="javadoc_location" value="jar:platform:/resource/gitblit/ext/jetty-all-7.2.2.v20101205-javadoc.jar!/"/>
- </attributes>
- </classpathentry>
<classpathentry kind="lib" path="ext/jcommander-1.17.jar" sourcepath="ext/jcommander-1.17-sources.jar">
<attributes>
<attribute name="javadoc_location" value="jar:platform:/resource/gitblit/ext/jcommander-1.17-javadoc.jar!/"/>
@@ -74,5 +69,10 @@
<attribute name="javadoc_location" value="jar:platform:/resource/gitblit/ext/bcmail-jdk16-1.46-javadoc.jar!/"/>
</attributes>
</classpathentry>
+ <classpathentry kind="lib" path="ext/jetty-all-7.4.1.v20110513.jar" sourcepath="ext/jetty-all-7.4.1.v20110513-sources.jar">
+ <attributes>
+ <attribute name="javadoc_location" value="jar:platform:/resource/gitblit/ext/jetty-all-7.2.2.v20101205-javadoc.jar!/"/>
+ </attributes>
+ </classpathentry>
<classpathentry kind="output" path="bin"/>
</classpath>
diff --git a/build.xml b/build.xml
index f47e5e9b..a3394c65 100644
--- a/build.xml
+++ b/build.xml
@@ -8,7 +8,12 @@
<target name="main">
- <!-- extract version number from source code -->
+ <!-- build dsate -->
+ <tstamp>
+ <format property="gb.buildDate" pattern="yyyy-MM-dd" />
+ </tstamp>
+
+ <!-- extract Git:Blit version number from source code -->
<loadfile property="gb.version" srcfile="${basedir}/src/com/gitblit/Constants.java">
<filterchain>
<linecontains>
@@ -20,6 +25,21 @@
<replacestring from="&quot;;" to="" />
<trim />
</tokenfilter>
+ </filterchain>
+ </loadfile>
+
+ <!-- extract JGit version number from source code -->
+ <loadfile property="jgit.version" srcfile="${basedir}/src/com/gitblit/Constants.java">
+ <filterchain>
+ <linecontains>
+ <contains value="public final static String JGIT_VERSION = " />
+ </linecontains>
+ <striplinebreaks />
+ <tokenfilter>
+ <replacestring from="public final static String JGIT_VERSION = &quot;" to="" />
+ <replacestring from="&quot;;" to="" />
+ <trim />
+ </tokenfilter>
</filterchain>
</loadfile>
<echo>Building Git:Blit ${gb.version}</echo>
@@ -118,22 +138,22 @@
<include name="book_16x16.png" />
<include name="blank.png" />
</fileset>
-
+
<!-- Copy Doc images -->
<fileset dir="${basedir}/docs">
<include name="*.png" />
<include name="*.js" />
</fileset>
</copy>
-
+
<!-- Copy Fancybox -->
<mkdir dir="${basedir}/site/fancybox" />
- <copy todir="${basedir}/site/fancybox">
- <fileset dir="${basedir}/docs/fancybox" >
+ <copy todir="${basedir}/site/fancybox">
+ <fileset dir="${basedir}/docs/fancybox">
<exclude name="thumbs.db" />
</fileset>
</copy>
-
+
<!-- Copy screenshot thumbnails -->
<mkdir dir="${basedir}/site/thumbs" />
<copy todir="${basedir}/site/thumbs">
@@ -141,7 +161,7 @@
<include name="*.png" />
</fileset>
</copy>
-
+
<!-- Copy screenshots -->
<mkdir dir="${basedir}/site/screenshots" />
<copy todir="${basedir}/site/screenshots">
@@ -150,11 +170,12 @@
</fileset>
</copy>
+ <!-- Build site pages -->
<java classpath="${project.build.dir}" classname="com.gitblit.BuildSite">
<classpath refid="master-classpath" />
<arg value="--sourceFolder" />
<arg value="${basedir}/docs" />
-
+
<arg value="--outputFolder" />
<arg value="${basedir}/site" />
@@ -163,9 +184,21 @@
<arg value="--pageFooter" />
<arg value="${basedir}/docs/page_footer.html" />
-
+
<arg value="--alias" />
<arg value="index=overview" />
+
+ <arg value="--substitute" />
+ <arg value="%VERSION%=${gb.version}" />
+
+ <arg value="--substitute" />
+ <arg value="%DISTRIBUTION%=${distribution.zipfile}" />
+
+ <arg value="--substitute" />
+ <arg value="%BUILDDATE%=${gb.buildDate}" />
+
+ <arg value="--substitute" />
+ <arg value="%JGIT%=${jgit.version}" />
</java>
</target>
diff --git a/distrib/gitblit.properties b/distrib/gitblit.properties
index de243d2a..d0e63757 100644
--- a/distrib/gitblit.properties
+++ b/distrib/gitblit.properties
@@ -69,7 +69,7 @@ web.datetimestampLongFormat = EEEE, MMMM d, yyyy h:mm a z
# Choose how to present the repositories list.
# grouped = group nested/subfolder repositories together (no sorting)
# flat = flat list of repositories (sorting allowed)
-web.repositoryListType = flat
+web.repositoryListType = grouped
# If using a grouped repository list and there are repositories at the
# root level of your repositories folder, you may specify the displayed
diff --git a/docs/00_index.mkd b/docs/00_index.mkd
index 6fdc0a1d..a43ffdcb 100644
--- a/docs/00_index.mkd
+++ b/docs/00_index.mkd
@@ -1,19 +1,17 @@
## Overview
Git:Blit is an open-source, integrated pure Java stack for managing, viewing, and serving [Git][git] repositories.
-Its designed primarily as a tool for small workgroups who want to host [Git][git] repositories on a Windows machine.
-
-Of course, since its pure Java it should run with any JVM on any platform, but there are already [many compelling Git solutions](https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools) for non-Windows environments.
+Its designed primarily as a tool for small workgroups who want to host [Git][git] repositories on a Windows machine. Having said that, it works equally well on any standard Linux distribution.
### Current Version
-[{0}](http://gitblit.com/{1}) based on [{2}][jgit] &nbsp; (*{3}*)
+[%VERSION%](http://gitblit.com/%DISTRIBUTION%) based on [%JGIT%][jgit] &nbsp; (*%BUILDDATE%*)
sources @ [Github][gitbltsrc]
### Design Principles
1. [KISS](http://en.wikipedia.org/wiki/KISS_principle)
2. Offer useful features for serving Git repositories. If feature is complex, refer to #1.
-3. All dependencies must be retrievable from a publicly accessible Maven repository.<br/>This is to ensure authenticity of dependencies and to keep the Git:Blit distribution svelte.
+3. All dependencies must be retrievable from a publicly accessible [Maven](http://maven.apache.org) repository.<br/>This is to ensure authenticity of dependencies and to keep the Git:Blit distribution svelte.
### Features
- Out-of-the-box integrated stack requiring minimal configuration
@@ -29,7 +27,7 @@ sources @ [Github][gitbltsrc]
</ul>
- Gitweb inspired UI
- Administrators may create, edit, rename, or delete repositories through the web UI
-- Administrators may create, edit, rename, or delete users through the web UI
+- Administrators may create, edit, or delete users through the web UI
- Repository Owners may edit repositories through the web UI
- Automatically generates a self-signed certificate for https communications
- Dates can optionally be displayed using the browser''s reported timezone
@@ -53,8 +51,6 @@ sources @ [Github][gitbltsrc]
- Git:Blit is an integrated, full-stack solution. There is no WAR build at this time.
### Todo List
-- Manual certificate generation with BouncyCastle
-- User list with edit and delete links
- Review spots where Git:Blit can cache data instead of abusing the disk
- stats
- users.properties access
@@ -90,8 +86,9 @@ The following dependencies are bundled with the Git:Blit zip distribution file.
- [google-code-prettify](http://code.google.com/p/google-code-prettify) (Apache 2.0)
- [JavaService](http://forge.ow2.org/projects/javaservice) (BSD and LGPL)
-- icons courtesy of [FatCow Hosting](http://www.fatcow.com/free-icons) (Creative Commons CC-BY)
- magnifying glass search icon courtesy of [Gnome](http://gnome.org) (Creative Commons CC-BY)
+- modified Git logo originally designed by [Henrik Nyh](http://henrik.nyh.se/2007/06/alternative-git-logo-and-favicon)
+- other icons courtesy of [FatCow Hosting](http://www.fatcow.com/free-icons) (Creative Commons CC-BY)
### Downloaded Dependencies
The following dependencies are automatically downloaded from the Apache Maven repository and from the Eclipse Maven repository when Git:Blit is launched for the first time.
diff --git a/docs/00_setup.mkd b/docs/00_setup.mkd
index 415ad474..a590b59a 100644
--- a/docs/00_setup.mkd
+++ b/docs/00_setup.mkd
@@ -1,6 +1,6 @@
## Setup and Configuration
-1. Download and unzip Git:Blit.<br/>
+1. Download and unzip [%VERSION%](http://gitblit.com/%DISTRIBUTION%).<br/>
*Its best to eliminate spaces in the path name as that can cause troubleshooting headaches.*
2. The server itself is configured through a simple text file.<br/>
Open `gitblit.properties` in your favorite text editor and make sure to review and set:
diff --git a/docs/01_faq.mkd b/docs/01_faq.mkd
index 94c6dbf4..23ee2b27 100644
--- a/docs/01_faq.mkd
+++ b/docs/01_faq.mkd
@@ -10,10 +10,17 @@ Its small. Its portable. Its easy to manage.
No. Git:Blit is based on [JGit][jgit] which is a pure Java implementation of the [Git version control system][git].<br/>
Everything you need for Git:Blit is either in the zip distribution file or automatically downloaded on execution.
+### Does Git:Blit use a database to store its data?
+No. Git:Blit stores its repository configuration information within the `.git/config` file and its user information in `users.properties` or whatever filename is configured in `gitblit.properties`.
+
+### I want to deploy Git:Blit into my own servlet container. Where is the WAR?
+At this time there is no WAR build available.
+
### Why doesn't Git:Blit support SSH?
-Git:Blit could integrate [Apache Mina](http://mina.apache.org) to provide SSH access. However, doing so violates design principle #1: KISS. SSH supports requires creating, exchanging, and managing SSH keys. While this is doable, its not simple like JGit's SmartHTTP implementation.
+Git:Blit could integrate [Apache Mina][mina] to provide SSH access. However, doing so violates Git:Blit's first design principle: [KISS](http://en.wikipedia.org/wiki/KISS_principle).<br/>
+SSH supports requires creating, exchanging, and managing SSH keys. While this is doable, its not simple like JGit's SmartHTTP implementation.
-You might consider [Gerrit](http://gerrit.googlecode.org) which supports SSH.
+You might consider running [Gerrit](http://gerrit.googlecode.org) which does integrate [Apache Mina][mina] and supports SSH or you might consider serving [Git][git] on Linux which would offer real SSH support and also allow use of [many other compelling Git solutions](https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools).
### What types of Search does Git:Blit support?
Git:Blit supports case-insensitive searches of *commit message* (default), *author*, and *committer*.<br/>
@@ -26,9 +33,10 @@ To search by *author* or *committer* use the following syntax in the search box:
Alternatively, you could enable the search type dropdown list in your `gitblit.properties` file.
### How do I run Git:Blit on port 80 or 443 in Linux?
-Tricky. Linux requires root permissions to serve on ports < 1024.<br/>
+Linux requires root permissions to serve on ports < 1024.<br/>
Run the server as *root* (security concern) or change the ports you are serving to 8080 (http) or 8443 (https).
[bitblt]: http://en.wikipedia.org/wiki/Bit_blit "Wikipedia Bitblt"
[jgit]: http://eclipse.org/jgit "Eclipse JGit Site"
-[git]: http://git-scm.com "Official Git Site" \ No newline at end of file
+[git]: http://git-scm.com "Official Git Site"
+[mina]: http://mina.apache.org " Apache Mina" \ No newline at end of file
diff --git a/docs/01_screenshots.mkd b/docs/01_screenshots.mkd
index 3d2061e9..14ec1793 100644
--- a/docs/01_screenshots.mkd
+++ b/docs/01_screenshots.mkd
@@ -1,8 +1,8 @@
## Screenshots
<table class="screenshots">
<tr><td>
- <a rel="screenshots_group" href="screenshots/00.png" title="Repository List">![Repositories](thumbs/00.png)</a>
- <br/>Repository List
+ <a rel="screenshots_group" href="screenshots/00.png" title="Repository & User List">![Repositories](thumbs/00.png)</a>
+ <br/>Repository & User List
</td><td>
<a rel="screenshots_group" href="screenshots/01.png" title="New User">![New User](thumbs/01.png)</a>
<br/>New User
diff --git a/docs/screenshots/00.png b/docs/screenshots/00.png
index 616b31c9..c9653f14 100644
--- a/docs/screenshots/00.png
+++ b/docs/screenshots/00.png
Binary files differ
diff --git a/docs/screenshots/raw/00.png b/docs/screenshots/raw/00.png
index 314f521c..eb501496 100644
--- a/docs/screenshots/raw/00.png
+++ b/docs/screenshots/raw/00.png
Binary files differ
diff --git a/docs/screenshots/thumbs/00.png b/docs/screenshots/thumbs/00.png
index 6aea6930..636631ff 100644
--- a/docs/screenshots/thumbs/00.png
+++ b/docs/screenshots/thumbs/00.png
Binary files differ
diff --git a/src/com/gitblit/Build.java b/src/com/gitblit/Build.java
index 89527260..1d2c0f18 100644
--- a/src/com/gitblit/Build.java
+++ b/src/com/gitblit/Build.java
@@ -268,7 +268,7 @@ public class Build {
public static final MavenObject JCOMMANDER = new MavenObject("jCommander", "com/beust", "jcommander", "1.17", 34000, 32000, 141000, "219a3540f3b27d7cc3b1d91d6ea046cd8723290e", "0bb50eec177acf0e94d58e0cf07262fe5164331d", "c7adc475ca40c288c93054e0f4fe58f3a98c0cb5");
- public static final MavenObject JETTY = new MavenObject("Jetty", "org/eclipse/jetty/aggregate", "jetty-all", "7.2.2.v20101205", 1430000, 965000, 3871000, "b9b7c812a732721c427e208c54fbb71ca17a2ee1", "cbc4fc72c4a646d8822bf7369c2101d4d5d1ff98", "34c87e11bba426fe97bfe23ccff12eda477c8f57");
+ public static final MavenObject JETTY = new MavenObject("Jetty", "org/eclipse/jetty/aggregate", "jetty-all", "7.4.1.v20110513", 1500000, 1000000, 4100000, "1e2de9ed25a7c6ae38717d5ffdc7cfcd6be4bd46", "7b6279d16ce8f663537d9faf55ea353e748dbbaa", "fa06212e751296f1a7abc15c843b135bf49a112b");
public static final MavenObject SERVLET = new MavenObject("Servlet 2.5", "javax/servlet", "servlet-api", "2.5", 105000, 158000, 0, "5959582d97d8b61f4d154ca9e495aafd16726e34", "021599814ad9a605b86f3e6381571beccd861a32", null);
diff --git a/src/com/gitblit/BuildSite.java b/src/com/gitblit/BuildSite.java
index 6ea8048c..dc42cf55 100644
--- a/src/com/gitblit/BuildSite.java
+++ b/src/com/gitblit/BuildSite.java
@@ -46,11 +46,11 @@ public class BuildSite {
Arrays.sort(markdownFiles);
Map<String, String> aliasMap = new HashMap<String, String>();
- for (String alias:params.aliases) {
- String [] values = alias.split("=");
+ for (String alias : params.aliases) {
+ String[] values = alias.split("=");
aliasMap.put(values[0], values[1]);
}
-
+
System.out.println(MessageFormat.format("Generating site from {0} Markdown Docs in {1} ", markdownFiles.length, sourceFolder.getAbsolutePath()));
String linkPattern = "<a href=''{0}''>{1}</a>";
StringBuilder sb = new StringBuilder();
@@ -66,7 +66,7 @@ public class BuildSite {
}
sb.setLength(sb.length() - 3);
sb.trimToSize();
-
+
String html_header = readContent(new File(params.pageHeader));
String html_footer = readContent(new File(params.pageFooter));
final String links = sb.toString();
@@ -76,16 +76,13 @@ public class BuildSite {
for (File file : markdownFiles) {
try {
String documentName = getDocumentName(file);
- String displayName = documentName;
- if (aliasMap.containsKey(documentName)) {
- displayName = aliasMap.get(documentName);
- }
String fileName = documentName + ".html";
System.out.println(MessageFormat.format(" {0} => {1}", file.getName(), fileName));
InputStreamReader reader = new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"));
String content = MarkdownUtils.transformMarkdown(reader);
- if (displayName.equalsIgnoreCase("overview")) {
- content = MessageFormat.format(content, Constants.VERSION, "gitblit-" + Constants.VERSION + ".zip", Constants.getJGitVersion(), date);
+ for (String token : params.substitutions) {
+ String [] kv = token.split("=");
+ content = content.replace(kv[0], kv[1]);
}
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(new File(destinationFolder, fileName)), Charset.forName("UTF-8"));
writer.write(header);
@@ -122,7 +119,7 @@ public class BuildSite {
// trim leading ##_ which is to control display order
return displayName.substring(3);
}
-
+
private static void usage(JCommander jc, ParameterException t) {
System.out.println(Constants.getRunningVersion());
System.out.println();
@@ -135,7 +132,7 @@ public class BuildSite {
}
System.exit(0);
}
-
+
@Parameters(separators = " ")
private static class Params {
@@ -154,5 +151,8 @@ public class BuildSite {
@Parameter(names = { "--alias" }, description = "Filename=Linkname aliases", required = false)
public List<String> aliases = new ArrayList<String>();
+ @Parameter(names = { "--substitute" }, description = "@TOKEN@=value", required = false)
+ public List<String> substitutions = new ArrayList<String>();
+
}
}
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java
index 7e19cefb..46f32084 100644
--- a/src/com/gitblit/Constants.java
+++ b/src/com/gitblit/Constants.java
@@ -10,6 +10,10 @@ public class Constants {
// and only use A-Z a-z 0-9 .-_ in the string.
public final static String VERSION = "0.1.0-SNAPSHOT";
+ // The build script extracts this exact line so be careful editing it
+ // and only use A-Z a-z 0-9 .-_ in the string.
+ public final static String JGIT_VERSION = "JGit 0.12.1";
+
public final static String ADMIN_ROLE = "#admin";
public final static String PROPERTIES_FILE = "gitblit.properties";
@@ -44,7 +48,7 @@ public class Constants {
}
public static String getJGitVersion() {
- return "JGit 0.12.1";
+ return JGIT_VERSION;
}
public static String getRunningVersion() {
diff --git a/src/com/gitblit/GitBlitServer.java b/src/com/gitblit/GitBlitServer.java
index 08c9b297..e9e44637 100644
--- a/src/com/gitblit/GitBlitServer.java
+++ b/src/com/gitblit/GitBlitServer.java
@@ -29,6 +29,7 @@ import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.session.HashSessionManager;
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
@@ -192,6 +193,16 @@ public class GitBlitServer {
rootContext.setServer(server);
rootContext.setWar(location.toExternalForm());
rootContext.setTempDirectory(tempDir);
+
+ // Mark all cookies HttpOnly so they are not accessible to JavaScript
+ // engines.
+ // http://erlend.oftedal.no/blog/?blogid=33
+ // https://www.owasp.org/index.php/HttpOnly#Browsers_Supporting_HttpOnly
+ HashSessionManager sessionManager = new HashSessionManager();
+ sessionManager.setHttpOnly(true);
+ // Use secure cookies if only serving https
+ sessionManager.setSecureCookies(params.port <= 0 && params.securePort > 0);
+ rootContext.getSessionHandler().setSessionManager(sessionManager);
// Wicket Filter
String wicketPathSpec = "/*";
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index d07f0bc6..b6dbc117 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -43,8 +43,8 @@ gb.head = HEAD
gb.blame = blame
gb.login = Login
gb.logout = Logout
-gb.username = Username
-gb.password = Password
+gb.username = username
+gb.password = password
gb.tagger = tagger
gb.moreHistory = more history...
gb.difftocurrent = diff to current
diff --git a/src/com/gitblit/wicket/WicketUtils.java b/src/com/gitblit/wicket/WicketUtils.java
index f0ccbf4b..761595b1 100644
--- a/src/com/gitblit/wicket/WicketUtils.java
+++ b/src/com/gitblit/wicket/WicketUtils.java
@@ -153,6 +153,10 @@ public class WicketUtils {
return new ContextRelativeResource("/com/gitblit/wicket/resources/" + file);
}
+ public static PageParameters newUsernameParameter(String username) {
+ return new PageParameters("user=" + username);
+ }
+
public static PageParameters newRepositoryParameter(String repositoryName) {
return new PageParameters("r=" + repositoryName);
}
diff --git a/src/com/gitblit/wicket/pages/EditUserPage.html b/src/com/gitblit/wicket/pages/EditUserPage.html
index c50bdbac..a27b7120 100644
--- a/src/com/gitblit/wicket/pages/EditUserPage.html
+++ b/src/com/gitblit/wicket/pages/EditUserPage.html
@@ -15,7 +15,7 @@
<form wicket:id="editForm">
<table class="plain">
<tbody>
- <tr><th><wicket:message key="gb.name"></wicket:message></th><td class="edit"><input type="text" wicket:id="username" id="username" size="30" tabindex="1" /></td></tr>
+ <tr><th><wicket:message key="gb.username"></wicket:message></th><td class="edit"><input type="text" wicket:id="username" id="username" size="30" tabindex="1" /></td></tr>
<tr><th><wicket:message key="gb.password"></wicket:message></th><td class="edit"><input type="password" wicket:id="password" size="30" tabindex="2" /></td></tr>
<tr><th><wicket:message key="gb.confirmPassword"></wicket:message></th><td class="edit"><input type="password" wicket:id="confirmPassword" size="30" tabindex="3" /></td></tr>
<tr><th><wicket:message key="gb.canAdmin"></wicket:message></th><td class="edit"><input type="checkbox" wicket:id="canAdmin" tabindex="6" /> &nbsp;<i><wicket:message key="gb.canAdminDescription"></wicket:message></i></td></tr>
diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.html b/src/com/gitblit/wicket/pages/RepositoriesPage.html
index d00c498a..da91cb2e 100644
--- a/src/com/gitblit/wicket/pages/RepositoriesPage.html
+++ b/src/com/gitblit/wicket/pages/RepositoriesPage.html
@@ -18,67 +18,10 @@
<div class="markdown" style="margin-top:-0.5em;padding-bottom:5px;" wicket:id="repositoriesMessage">[repositories message]</div>
- <div wicket:id="adminPanel">[admin links]</div>
-
- <table class="repositories">
- <span wicket:id="headerContent"></span>
- <tbody>
- <tr wicket:id="row">
- <span wicket:id="rowContent"></span>
- </tr>
- </tbody>
- </table>
-
- <wicket:fragment wicket:id="adminLinks">
- <!-- page nav links -->
- <div style="text-align: right;" class="admin_nav">
- <a wicket:id="newRepository"><wicket:message key="gb.newRepository"></wicket:message></a> | <a wicket:id="newUser"><wicket:message key="gb.newUser"></wicket:message></a> | <a wicket:id="editUsers"><wicket:message key="gb.editUsers"></wicket:message></a>
- </div>
- </wicket:fragment>
-
- <wicket:fragment wicket:id="repositoryAdminLinks">
- <span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | <a wicket:id="renameRepository"><wicket:message key="gb.rename">[rename]</wicket:message></a> | <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a></span>
- </wicket:fragment>
-
- <wicket:fragment wicket:id="repositoryOwnerLinks">
- <span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a></span>
- </wicket:fragment>
+ <div wicket:id="repositoriesPanel">[repositories panel]</div>
- <wicket:fragment wicket:id="flatHeader">
- <tr>
- <th wicket:id="orderByRepository"><wicket:message key="gb.repository">Repository</wicket:message></th>
- <th wicket:id="orderByDescription"><wicket:message key="gb.description">Description</wicket:message></th>
- <th wicket:id="orderByOwner"><wicket:message key="gb.owner">Owner</wicket:message></th>
- <th></th>
- <th wicket:id="orderByDate"><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
- <th></th>
- </tr>
- </wicket:fragment>
-
- <wicket:fragment wicket:id="groupHeader">
- <tr>
- <th><wicket:message key="gb.repository">Repository</wicket:message></th>
- <th><wicket:message key="gb.description">Description</wicket:message></th>
- <th><wicket:message key="gb.owner">Owner</wicket:message></th>
- <th></th>
- <th><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
- <th></th>
- </tr>
- </wicket:fragment>
-
- <wicket:fragment wicket:id="groupRow">
- <td colspan="6"><span wicket:id="groupName">[group name]</span></td>
- </wicket:fragment>
+ <div style="padding-top: 10px;"wicket:id="usersPanel">[users panel]</div>
- <wicket:fragment wicket:id="repositoryRow">
- <td><div class="list" wicket:id="repositoryName">[repository name]</div></td>
- <td><div class="list" wicket:id="repositoryDescription">[repository description]</div></td>
- <td class="author"><span wicket:id="repositoryOwner">[repository owner]</span></td>
- <td style="text-align: right;padding-right:10px;"><img class="inlineIcon" wicket:id="ticketsIcon" /><img class="inlineIcon" wicket:id="docsIcon" /><img class="inlineIcon" wicket:id="frozenIcon" /><img class="inlineIcon" wicket:id="accessRestrictionIcon" /></td>
- <td><span wicket:id="repositoryLastChange">[last change]</span></td>
- <td class="rightAlign"><span wicket:id="repositoryLinks"></span></td>
- </wicket:fragment>
-
</wicket:extend>
</body>
</html> \ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/RepositoriesPage.java b/src/com/gitblit/wicket/pages/RepositoriesPage.java
index 14a54266..32552f7e 100644
--- a/src/com/gitblit/wicket/pages/RepositoriesPage.java
+++ b/src/com/gitblit/wicket/pages/RepositoriesPage.java
@@ -4,50 +4,27 @@ import java.io.File;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import org.apache.wicket.Component;
-import org.apache.wicket.PageParameters;
-import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
-import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
-import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.html.link.BookmarkablePageLink;
-import org.apache.wicket.markup.html.panel.Fragment;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.markup.repeater.data.DataView;
-import org.apache.wicket.markup.repeater.data.IDataProvider;
-import org.apache.wicket.markup.repeater.data.ListDataProvider;
-import org.apache.wicket.model.IModel;
-import org.apache.wicket.model.Model;
import org.apache.wicket.resource.ContextRelativeResource;
-import com.gitblit.Constants.AccessRestrictionType;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.utils.MarkdownUtils;
import com.gitblit.utils.StringUtils;
-import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.BasePage;
import com.gitblit.wicket.GitBlitWebSession;
-import com.gitblit.wicket.LinkPanel;
import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.models.RepositoryModel;
-import com.gitblit.wicket.models.UserModel;
+import com.gitblit.wicket.panels.RepositoriesPanel;
+import com.gitblit.wicket.panels.UsersPanel;
public class RepositoriesPage extends BasePage {
public RepositoriesPage() {
super();
setupPage("", "");
-
+
final boolean showAdmin;
if (GitBlit.self().settings().getBoolean(Keys.web.authenticateAdminPages, true)) {
boolean allowAdmin = GitBlit.self().settings().getBoolean(Keys.web.allowAdministration, false);
@@ -65,12 +42,6 @@ public class RepositoriesPage extends BasePage {
}
}
- Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
- adminLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
- adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class));
- adminLinks.add(new BookmarkablePageLink<Void>("editUsers", RepositoriesPage.class));
- add(adminLinks.setVisible(showAdmin));
-
// display an error message cached from a redirect
String cachedMessage = GitBlitWebSession.get().clearErrorMessage();
if (!StringUtils.isEmpty(cachedMessage)) {
@@ -111,228 +82,7 @@ public class RepositoriesPage extends BasePage {
}
Component repositoriesMessage = new Label("repositoriesMessage", message).setEscapeModelStrings(false);
add(repositoriesMessage);
-
- final Map<AccessRestrictionType, String> accessRestrictionTranslations = getAccessRestrictions();
- final UserModel user = GitBlitWebSession.get().getUser();
- List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user);
- IDataProvider<RepositoryModel> dp;
-
- if (GitBlit.self().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
- Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();
- for (RepositoryModel model : models) {
- String rootPath = StringUtils.getRootPath(model.name);
- if (StringUtils.isEmpty(rootPath)) {
- rootPath = GitBlit.self().settings().getString(Keys.web.repositoryRootGroupName, " ");
- }
- if (!groups.containsKey(rootPath)) {
- groups.put(rootPath, new ArrayList<RepositoryModel>());
- }
- groups.get(rootPath).add(model);
- }
- List<String> roots = new ArrayList<String>(groups.keySet());
- Collections.sort(roots);
- List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
- for (String root : roots) {
- groupedModels.add(new GroupRepositoryModel(root));
- groupedModels.addAll(groups.get(root));
- }
- dp = new ListDataProvider<RepositoryModel>(groupedModels);
- } else {
- dp = new DataProvider(models);
- }
-
- DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
- private static final long serialVersionUID = 1L;
- int counter = 0;
-
- public void populateItem(final Item<RepositoryModel> item) {
- final RepositoryModel entry = item.getModelObject();
- if (entry instanceof GroupRepositoryModel) {
- Fragment row = new Fragment("rowContent", "groupRow", this);
- item.add(row);
- row.add(new Label("groupName", entry.name));
- WicketUtils.setCssClass(item, "group");
- return;
- }
- Fragment row = new Fragment("rowContent", "repositoryRow", this);
- item.add(row);
- if (entry.hasCommits) {
- // Existing repository
- PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
- row.add(new LinkPanel("repositoryName", "list", entry.name, SummaryPage.class, pp));
- row.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
- } else {
- // New repository
- row.add(new Label("repositoryName", entry.name + "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
- row.add(new Label("repositoryDescription", entry.description));
- }
-
- if (entry.useTickets) {
- row.add(WicketUtils.newImage("ticketsIcon", "bug_16x16.png", getString("gb.tickets")));
- } else {
- row.add(WicketUtils.newBlankImage("ticketsIcon"));
- }
-
- if (entry.useDocs) {
- row.add(WicketUtils.newImage("docsIcon", "book_16x16.png", getString("gb.docs")));
- } else {
- row.add(WicketUtils.newBlankImage("docsIcon"));
- }
-
- if (entry.isFrozen) {
- row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", getString("gb.isFrozen")));
- } else {
- row.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false));
- }
- switch (entry.accessRestriction) {
- case NONE:
- row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
- break;
- case PUSH:
- row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
- break;
- case CLONE:
- row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
- break;
- case VIEW:
- row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
- break;
- default:
- row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
- }
-
- row.add(new Label("repositoryOwner", entry.owner));
-
- String lastChange = TimeUtils.timeAgo(entry.lastChange);
- Label lastChangeLabel = new Label("repositoryLastChange", lastChange);
- row.add(lastChangeLabel);
- WicketUtils.setCssClass(lastChangeLabel, TimeUtils.timeAgoCss(entry.lastChange));
-
- boolean showOwner = user != null && user.getUsername().equalsIgnoreCase(entry.owner);
- if (showAdmin) {
- Fragment repositoryLinks = new Fragment("repositoryLinks", "repositoryAdminLinks", this);
- repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)));
- repositoryLinks.add(new BookmarkablePageLink<Void>("renameRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)).setEnabled(false));
- repositoryLinks.add(new BookmarkablePageLink<Void>("deleteRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)).setEnabled(false));
- row.add(repositoryLinks);
- } else if (showOwner) {
- Fragment repositoryLinks = new Fragment("repositoryLinks", "repositoryOwnerLinks", this);
- repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)));
- row.add(repositoryLinks);
- } else {
- row.add(new Label("repositoryLinks"));
- }
- WicketUtils.setAlternatingBackground(item, counter);
- counter++;
- }
- };
- add(dataView);
-
- if (dp instanceof SortableDataProvider<?>) {
- // add sortable header
- SortableDataProvider<?> sdp = (SortableDataProvider<?>) dp;
- Fragment fragment = new Fragment("headerContent", "flatHeader", this);
- fragment.add(newSort("orderByRepository", SortBy.repository, sdp, dataView));
- fragment.add(newSort("orderByDescription", SortBy.description, sdp, dataView));
- fragment.add(newSort("orderByOwner", SortBy.owner, sdp, dataView));
- fragment.add(newSort("orderByDate", SortBy.date, sdp, dataView));
- add(fragment);
- } else {
- // not sortable
- Fragment fragment = new Fragment("headerContent", "groupHeader", this);
- add(fragment);
- }
- }
-
- protected enum SortBy {
- repository, description, owner, date;
- }
-
- protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp, final DataView<?> dataView) {
- return new OrderByBorder(wicketId, field.name(), dp) {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected void onSortChanged() {
- dataView.setCurrentPage(0);
- }
- };
- }
-
- private class DataProvider extends SortableDataProvider<RepositoryModel> {
- private static final long serialVersionUID = 1L;
- private List<RepositoryModel> list = null;
-
- protected DataProvider(List<RepositoryModel> list) {
- this.list = list;
- setSort(SortBy.date.name(), false);
- }
-
- @Override
- public int size() {
- if (list == null)
- return 0;
- return list.size();
- }
-
- @Override
- public IModel<RepositoryModel> model(RepositoryModel header) {
- return new Model<RepositoryModel>(header);
- }
-
- @Override
- public Iterator<RepositoryModel> iterator(int first, int count) {
- SortParam sp = getSort();
- String prop = sp.getProperty();
- final boolean asc = sp.isAscending();
-
- if (prop == null || prop.equals(SortBy.date.name())) {
- Collections.sort(list, new Comparator<RepositoryModel>() {
- @Override
- public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
- return o1.lastChange.compareTo(o2.lastChange);
- return o2.lastChange.compareTo(o1.lastChange);
- }
- });
- } else if (prop.equals(SortBy.repository.name())) {
- Collections.sort(list, new Comparator<RepositoryModel>() {
- @Override
- public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
- return o1.name.compareTo(o2.name);
- return o2.name.compareTo(o1.name);
- }
- });
- } else if (prop.equals(SortBy.owner.name())) {
- Collections.sort(list, new Comparator<RepositoryModel>() {
- @Override
- public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
- return o1.owner.compareTo(o2.owner);
- return o2.owner.compareTo(o1.owner);
- }
- });
- } else if (prop.equals(SortBy.description.name())) {
- Collections.sort(list, new Comparator<RepositoryModel>() {
- @Override
- public int compare(RepositoryModel o1, RepositoryModel o2) {
- if (asc)
- return o1.description.compareTo(o2.description);
- return o2.description.compareTo(o1.description);
- }
- });
- }
- return list.subList(first, first + count).iterator();
- }
- }
-
- private class GroupRepositoryModel extends RepositoryModel {
-
- private static final long serialVersionUID = 1L;
-
- GroupRepositoryModel(String name) {
- super(name, "", "", new Date(0));
- }
+ add(new RepositoriesPanel("repositoriesPanel", showAdmin, getAccessRestrictions()));
+ add(new UsersPanel("usersPanel", showAdmin).setVisible(showAdmin));
}
}
diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.html b/src/com/gitblit/wicket/panels/RepositoriesPanel.html
new file mode 100644
index 00000000..a066b58e
--- /dev/null
+++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.html
@@ -0,0 +1,88 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
+ xml:lang="en"
+ lang="en">
+
+<body>
+<wicket:panel>
+
+ <div wicket:id="adminPanel">[admin links]</div>
+
+ <table class="repositories">
+ <span wicket:id="headerContent"></span>
+ <tbody>
+ <tr wicket:id="row">
+ <span wicket:id="rowContent"></span>
+ </tr>
+ </tbody>
+ </table>
+
+ <wicket:fragment wicket:id="adminLinks">
+ <!-- page nav links -->
+ <div class="admin_nav">
+ <wicket:link>
+ <img style="vertical-align: top;" src="/com/gitblit/wicket/resources/add_16x16.png"/>
+ </wicket:link>
+ <a wicket:id="newRepository">
+ <wicket:message key="gb.newRepository"></wicket:message>
+ </a>
+ </div>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="repositoryAdminLinks">
+ <span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a> | <a wicket:id="renameRepository"><wicket:message key="gb.rename">[rename]</wicket:message></a> | <a wicket:id="deleteRepository"><wicket:message key="gb.delete">[delete]</wicket:message></a></span>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="repositoryOwnerLinks">
+ <span class="link"><a wicket:id="editRepository"><wicket:message key="gb.edit">[edit]</wicket:message></a></span>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="flatRepositoryHeader">
+ <tr>
+ <th class="left" wicket:id="orderByRepository">
+ <wicket:link>
+ <img style="vertical-align: top; border: 1px solid #888;" src="/com/gitblit/wicket/resources/gitweb-favicon.png"/>
+ </wicket:link>
+ <wicket:message key="gb.repository">Repository</wicket:message>
+ </th>
+ <th wicket:id="orderByDescription"><wicket:message key="gb.description">Description</wicket:message></th>
+ <th wicket:id="orderByOwner"><wicket:message key="gb.owner">Owner</wicket:message></th>
+ <th></th>
+ <th wicket:id="orderByDate"><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
+ <th clas="right"></th>
+ </tr>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="groupRepositoryHeader">
+ <tr>
+ <th class="left">
+ <wicket:link>
+ <img style="vertical-align: top; border: 1px solid #888;" src="/com/gitblit/wicket/resources/gitweb-favicon.png"/>
+ </wicket:link>
+ <wicket:message key="gb.repository">Repository</wicket:message>
+ </th>
+ <th><wicket:message key="gb.description">Description</wicket:message></th>
+ <th><wicket:message key="gb.owner">Owner</wicket:message></th>
+ <th></th>
+ <th><wicket:message key="gb.lastChange">Last Change</wicket:message></th>
+ <th class="right"></th>
+ </tr>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="groupRepositoryRow">
+ <td colspan="6"><span wicket:id="groupName">[group name]</span></td>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="repositoryRow">
+ <td class="left"><div class="list" wicket:id="repositoryName">[repository name]</div></td>
+ <td><div class="list" wicket:id="repositoryDescription">[repository description]</div></td>
+ <td class="author"><span wicket:id="repositoryOwner">[repository owner]</span></td>
+ <td style="text-align: right;padding-right:10px;"><img class="inlineIcon" wicket:id="ticketsIcon" /><img class="inlineIcon" wicket:id="docsIcon" /><img class="inlineIcon" wicket:id="frozenIcon" /><img class="inlineIcon" wicket:id="accessRestrictionIcon" /></td>
+ <td><span wicket:id="repositoryLastChange">[last change]</span></td>
+ <td class="rightAlign"><span wicket:id="repositoryLinks"></span></td>
+ </wicket:fragment>
+
+</wicket:panel>
+</body>
+</html> \ No newline at end of file
diff --git a/src/com/gitblit/wicket/panels/RepositoriesPanel.java b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
new file mode 100644
index 00000000..6d05888e
--- /dev/null
+++ b/src/com/gitblit/wicket/panels/RepositoriesPanel.java
@@ -0,0 +1,274 @@
+package com.gitblit.wicket.panels;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.extensions.markup.html.repeater.data.sort.OrderByBorder;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortParam;
+import org.apache.wicket.extensions.markup.html.repeater.util.SortableDataProvider;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.IDataProvider;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.apache.wicket.model.IModel;
+import org.apache.wicket.model.Model;
+
+import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.TimeUtils;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.models.RepositoryModel;
+import com.gitblit.wicket.models.UserModel;
+import com.gitblit.wicket.pages.EditRepositoryPage;
+import com.gitblit.wicket.pages.SummaryPage;
+
+
+public class RepositoriesPanel extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ public RepositoriesPanel(String wicketId, final boolean showAdmin, final Map<AccessRestrictionType, String> accessRestrictionTranslations) {
+ super(wicketId);
+
+ final UserModel user = GitBlitWebSession.get().getUser();
+ List<RepositoryModel> models = GitBlit.self().getRepositoryModels(user);
+ IDataProvider<RepositoryModel> dp;
+
+ Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
+ adminLinks.add(new BookmarkablePageLink<Void>("newRepository", EditRepositoryPage.class));
+ add(adminLinks.setVisible(showAdmin));
+
+ if (GitBlit.self().settings().getString(Keys.web.repositoryListType, "flat").equalsIgnoreCase("grouped")) {
+ Map<String, List<RepositoryModel>> groups = new HashMap<String, List<RepositoryModel>>();
+ for (RepositoryModel model : models) {
+ String rootPath = StringUtils.getRootPath(model.name);
+ if (StringUtils.isEmpty(rootPath)) {
+ rootPath = GitBlit.self().settings().getString(Keys.web.repositoryRootGroupName, " ");
+ }
+ if (!groups.containsKey(rootPath)) {
+ groups.put(rootPath, new ArrayList<RepositoryModel>());
+ }
+ groups.get(rootPath).add(model);
+ }
+ List<String> roots = new ArrayList<String>(groups.keySet());
+ Collections.sort(roots);
+ List<RepositoryModel> groupedModels = new ArrayList<RepositoryModel>();
+ for (String root : roots) {
+ List<RepositoryModel> subModels = groups.get(root);
+ groupedModels.add(new GroupRepositoryModel(root + " (" + subModels.size() + ")"));
+ groupedModels.addAll(subModels);
+ }
+ dp = new ListDataProvider<RepositoryModel>(groupedModels);
+ } else {
+ dp = new DataProvider(models);
+ }
+
+ DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("row", dp) {
+ private static final long serialVersionUID = 1L;
+ int counter = 0;
+
+ public void populateItem(final Item<RepositoryModel> item) {
+ final RepositoryModel entry = item.getModelObject();
+ if (entry instanceof GroupRepositoryModel) {
+ Fragment row = new Fragment("rowContent", "groupRepositoryRow", this);
+ item.add(row);
+ row.add(new Label("groupName", entry.name));
+ WicketUtils.setCssClass(item, "group");
+ return;
+ }
+ Fragment row = new Fragment("rowContent", "repositoryRow", this);
+ item.add(row);
+ if (entry.hasCommits) {
+ // Existing repository
+ PageParameters pp = WicketUtils.newRepositoryParameter(entry.name);
+ row.add(new LinkPanel("repositoryName", "list", entry.name, SummaryPage.class, pp));
+ row.add(new LinkPanel("repositoryDescription", "list", entry.description, SummaryPage.class, pp));
+ } else {
+ // New repository
+ row.add(new Label("repositoryName", entry.name + "<span class='empty'>(empty)</span>").setEscapeModelStrings(false));
+ row.add(new Label("repositoryDescription", entry.description));
+ }
+
+ if (entry.useTickets) {
+ row.add(WicketUtils.newImage("ticketsIcon", "bug_16x16.png", getString("gb.tickets")));
+ } else {
+ row.add(WicketUtils.newBlankImage("ticketsIcon"));
+ }
+
+ if (entry.useDocs) {
+ row.add(WicketUtils.newImage("docsIcon", "book_16x16.png", getString("gb.docs")));
+ } else {
+ row.add(WicketUtils.newBlankImage("docsIcon"));
+ }
+
+ if (entry.isFrozen) {
+ row.add(WicketUtils.newImage("frozenIcon", "cold_16x16.png", getString("gb.isFrozen")));
+ } else {
+ row.add(WicketUtils.newClearPixel("frozenIcon").setVisible(false));
+ }
+ switch (entry.accessRestriction) {
+ case NONE:
+ row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
+ break;
+ case PUSH:
+ row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_go_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
+ break;
+ case CLONE:
+ row.add(WicketUtils.newImage("accessRestrictionIcon", "lock_pull_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
+ break;
+ case VIEW:
+ row.add(WicketUtils.newImage("accessRestrictionIcon", "shield_16x16.png", accessRestrictionTranslations.get(entry.accessRestriction)));
+ break;
+ default:
+ row.add(WicketUtils.newBlankImage("accessRestrictionIcon"));
+ }
+
+ row.add(new Label("repositoryOwner", entry.owner));
+
+ String lastChange = TimeUtils.timeAgo(entry.lastChange);
+ Label lastChangeLabel = new Label("repositoryLastChange", lastChange);
+ row.add(lastChangeLabel);
+ WicketUtils.setCssClass(lastChangeLabel, TimeUtils.timeAgoCss(entry.lastChange));
+
+ boolean showOwner = user != null && user.getUsername().equalsIgnoreCase(entry.owner);
+ if (showAdmin) {
+ Fragment repositoryLinks = new Fragment("repositoryLinks", "repositoryAdminLinks", this);
+ repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)));
+ repositoryLinks.add(new BookmarkablePageLink<Void>("renameRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)).setEnabled(false));
+ repositoryLinks.add(new BookmarkablePageLink<Void>("deleteRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)).setEnabled(false));
+ row.add(repositoryLinks);
+ } else if (showOwner) {
+ Fragment repositoryLinks = new Fragment("repositoryLinks", "repositoryOwnerLinks", this);
+ repositoryLinks.add(new BookmarkablePageLink<Void>("editRepository", EditRepositoryPage.class, WicketUtils.newRepositoryParameter(entry.name)));
+ row.add(repositoryLinks);
+ } else {
+ row.add(new Label("repositoryLinks"));
+ }
+ WicketUtils.setAlternatingBackground(item, counter);
+ counter++;
+ }
+ };
+ add(dataView);
+
+ if (dp instanceof SortableDataProvider<?>) {
+ // add sortable header
+ SortableDataProvider<?> sdp = (SortableDataProvider<?>) dp;
+ Fragment fragment = new Fragment("headerContent", "flatRepositoryHeader", this);
+ fragment.add(newSort("orderByRepository", SortBy.repository, sdp, dataView));
+ fragment.add(newSort("orderByDescription", SortBy.description, sdp, dataView));
+ fragment.add(newSort("orderByOwner", SortBy.owner, sdp, dataView));
+ fragment.add(newSort("orderByDate", SortBy.date, sdp, dataView));
+ add(fragment);
+ } else {
+ // not sortable
+ Fragment fragment = new Fragment("headerContent", "groupRepositoryHeader", this);
+ add(fragment);
+ }
+ }
+
+ private class GroupRepositoryModel extends RepositoryModel {
+
+ private static final long serialVersionUID = 1L;
+
+ GroupRepositoryModel(String name) {
+ super(name, "", "", new Date(0));
+ }
+ }
+
+ protected enum SortBy {
+ repository, description, owner, date;
+ }
+
+ protected OrderByBorder newSort(String wicketId, SortBy field, SortableDataProvider<?> dp, final DataView<?> dataView) {
+ return new OrderByBorder(wicketId, field.name(), dp) {
+ private static final long serialVersionUID = 1L;
+
+ @Override
+ protected void onSortChanged() {
+ dataView.setCurrentPage(0);
+ }
+ };
+ }
+
+ private class DataProvider extends SortableDataProvider<RepositoryModel> {
+ private static final long serialVersionUID = 1L;
+ private List<RepositoryModel> list = null;
+
+ protected DataProvider(List<RepositoryModel> list) {
+ this.list = list;
+ setSort(SortBy.date.name(), false);
+ }
+
+ @Override
+ public int size() {
+ if (list == null)
+ return 0;
+ return list.size();
+ }
+
+ @Override
+ public IModel<RepositoryModel> model(RepositoryModel header) {
+ return new Model<RepositoryModel>(header);
+ }
+
+ @Override
+ public Iterator<RepositoryModel> iterator(int first, int count) {
+ SortParam sp = getSort();
+ String prop = sp.getProperty();
+ final boolean asc = sp.isAscending();
+
+ if (prop == null || prop.equals(SortBy.date.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.lastChange.compareTo(o2.lastChange);
+ return o2.lastChange.compareTo(o1.lastChange);
+ }
+ });
+ } else if (prop.equals(SortBy.repository.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.name.compareTo(o2.name);
+ return o2.name.compareTo(o1.name);
+ }
+ });
+ } else if (prop.equals(SortBy.owner.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.owner.compareTo(o2.owner);
+ return o2.owner.compareTo(o1.owner);
+ }
+ });
+ } else if (prop.equals(SortBy.description.name())) {
+ Collections.sort(list, new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ if (asc)
+ return o1.description.compareTo(o2.description);
+ return o2.description.compareTo(o1.description);
+ }
+ });
+ }
+ return list.subList(first, first + count).iterator();
+ }
+ }
+}
diff --git a/src/com/gitblit/wicket/panels/UsersPanel.html b/src/com/gitblit/wicket/panels/UsersPanel.html
new file mode 100644
index 00000000..39074b2f
--- /dev/null
+++ b/src/com/gitblit/wicket/panels/UsersPanel.html
@@ -0,0 +1,48 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd"
+ xml:lang="en"
+ lang="en">
+
+<body>
+<wicket:panel>
+
+ <div wicket:id="adminPanel">[admin links]</div>
+
+ <table class="repositories">
+ <tr>
+ <th class="left">
+ <wicket:link>
+ <img style="vertical-align: top; border: 1px solid #888; background-color: white;" src="/com/gitblit/wicket/resources/user_16x16.png"/>
+ </wicket:link>
+ <wicket:message key="gb.username">[username]</wicket:message>
+ </th>
+ <th class="right"></th>
+ </tr>
+ <tbody>
+ <tr wicket:id="userRow">
+ <td class="left" ><div class="list" wicket:id="username">[username]</div></td>
+ <td class="rightAlign"><span wicket:id="userLinks"></span></td>
+ </tr>
+ </tbody>
+ </table>
+
+ <wicket:fragment wicket:id="adminLinks">
+ <!-- page nav links -->
+ <div class="admin_nav">
+ <wicket:link>
+ <img style="vertical-align: top;" src="/com/gitblit/wicket/resources/add_16x16.png"/>
+ </wicket:link>
+ <a wicket:id="newUser">
+ <wicket:message key="gb.newUser"></wicket:message>
+ </a>
+ </div>
+ </wicket:fragment>
+
+ <wicket:fragment wicket:id="userAdminLinks">
+ <span class="link"><a wicket:id="editUser"><wicket:message key="gb.edit">[edit]</wicket:message></a> | <a wicket:id="deleteUser"><wicket:message key="gb.delete">[delete]</wicket:message></a></span>
+ </wicket:fragment>
+
+</wicket:panel>
+</body>
+</html> \ No newline at end of file
diff --git a/src/com/gitblit/wicket/panels/UsersPanel.java b/src/com/gitblit/wicket/panels/UsersPanel.java
new file mode 100644
index 00000000..17212723
--- /dev/null
+++ b/src/com/gitblit/wicket/panels/UsersPanel.java
@@ -0,0 +1,46 @@
+package com.gitblit.wicket.panels;
+
+import org.apache.wicket.markup.html.link.BookmarkablePageLink;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+
+import com.gitblit.GitBlit;
+import com.gitblit.wicket.LinkPanel;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.pages.EditUserPage;
+import com.gitblit.wicket.pages.RepositoriesPage;
+
+public class UsersPanel extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ public UsersPanel(String wicketId, final boolean showAdmin) {
+ super(wicketId);
+
+ Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);
+ adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class));
+ add(adminLinks.setVisible(showAdmin));
+
+ DataView<String> usersView = new DataView<String>("userRow", new ListDataProvider<String>(GitBlit.self().getAllUsernames())) {
+ private static final long serialVersionUID = 1L;
+ private int counter = 0;
+
+ public void populateItem(final Item<String> item) {
+ final String entry = item.getModelObject();
+ LinkPanel editLink = new LinkPanel("username", "list", entry, EditUserPage.class, WicketUtils.newUsernameParameter(entry));
+ WicketUtils.setHtmlTooltip(editLink, getString("gb.edit") + " " + entry);
+ item.add(editLink);
+ Fragment userLinks = new Fragment("userLinks", "userAdminLinks", this);
+ userLinks.add(new BookmarkablePageLink<Void>("editUser", EditUserPage.class, WicketUtils.newUsernameParameter(entry)));
+ userLinks.add(new BookmarkablePageLink<Void>("deleteUser", RepositoriesPage.class, WicketUtils.newUsernameParameter(entry)).setEnabled(false));
+ item.add(userLinks);
+
+ WicketUtils.setAlternatingBackground(item, counter);
+ counter++;
+ }
+ };
+ add(usersView.setVisible(showAdmin));
+ }
+}
diff --git a/src/com/gitblit/wicket/resources/add_16x16.png b/src/com/gitblit/wicket/resources/add_16x16.png
new file mode 100644
index 00000000..0ea124a7
--- /dev/null
+++ b/src/com/gitblit/wicket/resources/add_16x16.png
Binary files differ
diff --git a/src/com/gitblit/wicket/resources/gitblit.css b/src/com/gitblit/wicket/resources/gitblit.css
index 3fa1fcf1..4a971a6f 100644
--- a/src/com/gitblit/wicket/resources/gitblit.css
+++ b/src/com/gitblit/wicket/resources/gitblit.css
@@ -190,6 +190,10 @@ div.page_nav2 {
}
div.admin_nav {
+ border: 1px solid #888;
+ border-bottom: 0px;
+ background:#dae0d2;
+ text-align: right;
padding: 5px 5px 5px 2px;
}
@@ -493,7 +497,7 @@ table.plain td.edit input:focus, table.plain td.edit input:hover{
border: 1px solid orange;
}
-table.pretty, table.repositories, table.comments {
+table.pretty, table.comments {
margin-bottom:5px;
border-spacing: 0px;
border-left: 1px solid #bbb;
@@ -522,6 +526,11 @@ table.comments td {
line-height: 17px;
}
+table.repositories {
+ margin-bottom:5px;
+ border-spacing: 0px;
+}
+
table.repositories th {
background-color:#D2C3AF;
padding: 4px;
@@ -529,10 +538,28 @@ table.repositories th {
border-bottom: 1px solid #808080;
}
+table.repositories th.left, table.repositories td.left {
+ border-left: 1px solid #808080;
+ padding-left: 5px;
+}
+
+table.repositories td.left {
+ padding-left: 10px;
+}
+
+table.repositories th.right, table.repositories td.right {
+ border-right: 1px solid #808080;
+}
+
table.repositories td {
padding: 2px;
}
+table.repositories td.rightAlign {
+ text-align: right;
+ border-right: 1px solid #808080;
+}
+
table.repositories td.icon img {
vertical-align: top;
}
@@ -552,6 +579,20 @@ table.repositories th.wicket_orderDown a, table.repositories th.wicket_orderUp a
font-weight: bold;
}
+table.repositories tr.group {
+ background-color: #E66C2C;
+}
+
+table.repositories tr.group td {
+ font-weight: bold;
+ border-bottom: 1px solid orange;
+ color: white;
+ background-color: #E66C2C;
+ border-left: 1px solid #808080;
+ border-right: 1px solid #808080;
+ padding-left: 5px;
+}
+
table.palette { border:0;}
table.palette td.header {
font-weight: bold;
@@ -570,17 +611,6 @@ tr th.wicket_orderDown a {background-image: url(arrow_down.png); }
tr th.wicket_orderUp a { background-image: url(arrow_up.png); }
tr th.wicket_orderNone a { background-image: url(arrow_off.png); }
-tr.group {
- background-color: #E66C2C;
-}
-
-tr.group td {
- font-weight: bold;
- border-bottom: 1px solid orange;
- color: white;
- background-color: #E66C2C;
-}
-
tr.light {
background-color: #ffffff;
}
diff --git a/src/com/gitblit/wicket/resources/gitweb-favicon.png b/src/com/gitblit/wicket/resources/gitweb-favicon.png
new file mode 100644
index 00000000..de637c06
--- /dev/null
+++ b/src/com/gitblit/wicket/resources/gitweb-favicon.png
Binary files differ
diff --git a/src/com/gitblit/wicket/resources/user_16x16.png b/src/com/gitblit/wicket/resources/user_16x16.png
new file mode 100644
index 00000000..d5edd4d4
--- /dev/null
+++ b/src/com/gitblit/wicket/resources/user_16x16.png
Binary files differ