summaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/main')
-rw-r--r--src/main/distrib/data/gitblit.properties10
-rw-r--r--src/main/java/com/gitblit/git/ReceiveHook.java4
-rw-r--r--src/main/java/com/gitblit/models/DailyLogEntry.java2
-rw-r--r--src/main/java/com/gitblit/models/RefLogEntry.java (renamed from src/main/java/com/gitblit/models/PushLogEntry.java)6
-rw-r--r--src/main/java/com/gitblit/utils/RefLogUtils.java (renamed from src/main/java/com/gitblit/utils/PushLogUtils.java)163
-rw-r--r--src/main/java/com/gitblit/wicket/GitBlitWebApp.java8
-rw-r--r--src/main/java/com/gitblit/wicket/GitBlitWebApp.properties11
-rw-r--r--src/main/java/com/gitblit/wicket/pages/DashboardPage.html100
-rw-r--r--src/main/java/com/gitblit/wicket/pages/DashboardPage.java249
-rw-r--r--src/main/java/com/gitblit/wicket/pages/MyDashboardPage.html158
-rw-r--r--src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java311
-rw-r--r--src/main/java/com/gitblit/wicket/pages/OverviewPage.html2
-rw-r--r--src/main/java/com/gitblit/wicket/pages/OverviewPage.java8
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ProjectPage.html106
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ProjectPage.java189
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ProjectsPage.html1
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ProjectsPage.java109
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ReflogPage.html (renamed from src/main/java/com/gitblit/wicket/pages/PushesPage.html)4
-rw-r--r--src/main/java/com/gitblit/wicket/pages/ReflogPage.java (renamed from src/main/java/com/gitblit/wicket/pages/PushesPage.java)22
-rw-r--r--src/main/java/com/gitblit/wicket/pages/RepositoryPage.java6
-rw-r--r--src/main/java/com/gitblit/wicket/pages/RootPage.java2
-rw-r--r--src/main/java/com/gitblit/wicket/panels/DigestsPanel.html (renamed from src/main/java/com/gitblit/wicket/panels/PushesPanel.html)9
-rw-r--r--src/main/java/com/gitblit/wicket/panels/DigestsPanel.java273
-rw-r--r--src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html2
-rw-r--r--src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java2
-rw-r--r--src/main/java/com/gitblit/wicket/panels/PushesPanel.java381
-rw-r--r--src/main/java/com/gitblit/wicket/panels/ReflogPanel.html43
-rw-r--r--src/main/java/com/gitblit/wicket/panels/ReflogPanel.java305
-rw-r--r--src/main/resources/gitblit.css22
29 files changed, 1379 insertions, 1129 deletions
diff --git a/src/main/distrib/data/gitblit.properties b/src/main/distrib/data/gitblit.properties
index 9f7eb778..7936bc2f 100644
--- a/src/main/distrib/data/gitblit.properties
+++ b/src/main/distrib/data/gitblit.properties
@@ -853,17 +853,17 @@ web.summaryRefsCount = 5
# SINCE 0.5.0
web.itemsPerPage = 50
-# The number of pushes to display on the overview page
+# The number of reflog changes to display on the overview page
# Value must exceed 0 else default of 5 is used
#
# SINCE 1.3.0
-web.overviewPushCount = 5
+web.overviewReflogCount = 5
-# The number of pushes to show on a push page before show the first, prev, next
-# pagination links. A default of 10 is used for any invalid value.
+# The number of reflog changes to show on a reflog page before show the first,
+# prev, next pagination links. A default of 10 is used for any invalid value.
#
# SINCE 1.3.0
-web.pushesPerPage = 10
+web.reflogChangesPerPage = 10
# Registered file extensions to ignore during Lucene indexing
#
diff --git a/src/main/java/com/gitblit/git/ReceiveHook.java b/src/main/java/com/gitblit/git/ReceiveHook.java
index 3e00b381..e3435ffb 100644
--- a/src/main/java/com/gitblit/git/ReceiveHook.java
+++ b/src/main/java/com/gitblit/git/ReceiveHook.java
@@ -45,7 +45,7 @@ import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.ClientLogger;
import com.gitblit.utils.JGitUtils;
-import com.gitblit.utils.PushLogUtils;
+import com.gitblit.utils.RefLogUtils;
import com.gitblit.utils.StringUtils;
/**
@@ -256,7 +256,7 @@ public class ReceiveHook implements PreReceiveHook, PostReceiveHook {
// update push log
try {
- PushLogUtils.updatePushLog(user, rp.getRepository(), commands);
+ RefLogUtils.updateRefLog(user, rp.getRepository(), commands);
logger.debug(MessageFormat.format("{0} push log updated", repository.name));
} catch (Exception e) {
logger.error(MessageFormat.format("Failed to update {0} pushlog", repository.name), e);
diff --git a/src/main/java/com/gitblit/models/DailyLogEntry.java b/src/main/java/com/gitblit/models/DailyLogEntry.java
index a459d76f..41f13818 100644
--- a/src/main/java/com/gitblit/models/DailyLogEntry.java
+++ b/src/main/java/com/gitblit/models/DailyLogEntry.java
@@ -28,7 +28,7 @@ import org.eclipse.jgit.transport.ReceiveCommand;
*
* @author James Moger
*/
-public class DailyLogEntry extends PushLogEntry implements Serializable {
+public class DailyLogEntry extends RefLogEntry implements Serializable {
private static final long serialVersionUID = 1L;
diff --git a/src/main/java/com/gitblit/models/PushLogEntry.java b/src/main/java/com/gitblit/models/RefLogEntry.java
index 77bed386..54d17771 100644
--- a/src/main/java/com/gitblit/models/PushLogEntry.java
+++ b/src/main/java/com/gitblit/models/RefLogEntry.java
@@ -39,7 +39,7 @@ import com.gitblit.utils.StringUtils;
*
* @author James Moger
*/
-public class PushLogEntry implements Serializable, Comparable<PushLogEntry> {
+public class RefLogEntry implements Serializable, Comparable<RefLogEntry> {
private static final long serialVersionUID = 1L;
@@ -67,7 +67,7 @@ public class PushLogEntry implements Serializable, Comparable<PushLogEntry> {
* @param user
* the user who pushed
*/
- public PushLogEntry(String repository, Date date, UserModel user) {
+ public RefLogEntry(String repository, Date date, UserModel user) {
this.repository = repository;
this.date = date;
this.user = user;
@@ -317,7 +317,7 @@ public class PushLogEntry implements Serializable, Comparable<PushLogEntry> {
}
@Override
- public int compareTo(PushLogEntry o) {
+ public int compareTo(RefLogEntry o) {
// reverse chronological order
return o.date.compareTo(date);
}
diff --git a/src/main/java/com/gitblit/utils/PushLogUtils.java b/src/main/java/com/gitblit/utils/RefLogUtils.java
index fed5b195..ce03a163 100644
--- a/src/main/java/com/gitblit/utils/PushLogUtils.java
+++ b/src/main/java/com/gitblit/utils/RefLogUtils.java
@@ -41,6 +41,7 @@ import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.RefRename;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
@@ -55,23 +56,23 @@ import org.slf4j.LoggerFactory;
import com.gitblit.Constants;
import com.gitblit.models.DailyLogEntry;
import com.gitblit.models.PathModel.PathChangeModel;
-import com.gitblit.models.PushLogEntry;
+import com.gitblit.models.RefLogEntry;
import com.gitblit.models.RefModel;
import com.gitblit.models.RepositoryCommit;
import com.gitblit.models.UserModel;
/**
- * Utility class for maintaining a pushlog within a git repository on an
+ * Utility class for maintaining a reflog within a git repository on an
* orphan branch.
*
* @author James Moger
*
*/
-public class PushLogUtils {
+public class RefLogUtils {
- public static final String GB_PUSHES = "refs/gitblit/pushes";
+ private static final String GB_REFLOG = "refs/gitblit/reflog";
- static final Logger LOGGER = LoggerFactory.getLogger(PushLogUtils.class);
+ private static final Logger LOGGER = LoggerFactory.getLogger(RefLogUtils.class);
/**
* Log an error message and exception.
@@ -97,17 +98,39 @@ public class PushLogUtils {
}
/**
- * Returns a RefModel for the gb-pushes branch in the repository. If the
+ * Returns a RefModel for the reflog branch in the repository. If the
* branch can not be found, null is returned.
*
* @param repository
- * @return a refmodel for the gb-pushes branch or null
+ * @return a refmodel for the reflog branch or null
*/
- public static RefModel getPushLogBranch(Repository repository) {
+ public static RefModel getRefLogBranch(Repository repository) {
List<RefModel> refs = JGitUtils.getRefs(repository, com.gitblit.Constants.R_GITBLIT);
+ RefModel pushLog = null;
+ final String GB_PUSHES = "refs/gitblit/pushes";
for (RefModel ref : refs) {
- if (ref.reference.getName().equals(GB_PUSHES)) {
+ if (ref.reference.getName().equals(GB_REFLOG)) {
return ref;
+ } else if (ref.reference.getName().equals(GB_PUSHES)) {
+ pushLog = ref;
+ }
+ }
+ if (pushLog != null) {
+ // rename refs/gitblit/pushes to refs/gitblit/reflog
+ RefRename cmd;
+ try {
+ cmd = repository.renameRef(GB_PUSHES, GB_REFLOG);
+ cmd.setRefLogIdent(new PersonIdent("Gitblit", "gitblit@localhost"));
+ cmd.setRefLogMessage("renamed " + GB_PUSHES + " => " + GB_REFLOG);
+ Result res = cmd.rename();
+ switch (res) {
+ case RENAMED:
+ return getRefLogBranch(repository);
+ default:
+ LOGGER.error("failed to rename " + GB_PUSHES + " => " + GB_REFLOG + " (" + res.name() + ")");
+ }
+ } catch (IOException e) {
+ LOGGER.error("failed to rename pushlog", e);
}
}
return null;
@@ -133,25 +156,25 @@ public class PushLogUtils {
}
/**
- * Updates a push log.
+ * Updates the reflog with the received commands.
*
* @param user
* @param repository
* @param commands
* @return true, if the update was successful
*/
- public static boolean updatePushLog(UserModel user, Repository repository,
+ public static boolean updateRefLog(UserModel user, Repository repository,
Collection<ReceiveCommand> commands) {
- RefModel pushlogBranch = getPushLogBranch(repository);
- if (pushlogBranch == null) {
- JGitUtils.createOrphanBranch(repository, GB_PUSHES, null);
+ RefModel reflogBranch = getRefLogBranch(repository);
+ if (reflogBranch == null) {
+ JGitUtils.createOrphanBranch(repository, GB_REFLOG, null);
}
boolean success = false;
String message = "push";
try {
- ObjectId headId = repository.resolve(GB_PUSHES + "^{commit}");
+ ObjectId headId = repository.resolve(GB_REFLOG + "^{commit}");
ObjectInserter odi = repository.newObjectInserter();
try {
// Create the in-memory index of the push log entry
@@ -184,7 +207,7 @@ public class PushLogUtils {
RevWalk revWalk = new RevWalk(repository);
try {
RevCommit revCommit = revWalk.parseCommit(commitId);
- RefUpdate ru = repository.updateRef(GB_PUSHES);
+ RefUpdate ru = repository.updateRef(GB_REFLOG);
ru.setNewObjectId(commitId);
ru.setExpectedOldObjectId(headId);
ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
@@ -201,7 +224,7 @@ public class PushLogUtils {
ru.getRef(), rc);
default:
throw new JGitInternalException(MessageFormat.format(
- JGitText.get().updatingRefFailed, GB_PUSHES, commitId.toString(),
+ JGitText.get().updatingRefFailed, GB_REFLOG, commitId.toString(),
rc));
}
} finally {
@@ -211,7 +234,7 @@ public class PushLogUtils {
odi.release();
}
} catch (Throwable t) {
- error(t, repository, "Failed to commit pushlog entry to {0}");
+ error(t, repository, "Failed to commit reflog entry to {0}");
}
return success;
}
@@ -316,25 +339,25 @@ public class PushLogUtils {
return inCoreIndex;
}
- public static List<PushLogEntry> getPushLog(String repositoryName, Repository repository) {
- return getPushLog(repositoryName, repository, null, 0, -1);
+ public static List<RefLogEntry> getRefLog(String repositoryName, Repository repository) {
+ return getRefLog(repositoryName, repository, null, 0, -1);
}
- public static List<PushLogEntry> getPushLog(String repositoryName, Repository repository, int maxCount) {
- return getPushLog(repositoryName, repository, null, 0, maxCount);
+ public static List<RefLogEntry> getRefLog(String repositoryName, Repository repository, int maxCount) {
+ return getRefLog(repositoryName, repository, null, 0, maxCount);
}
- public static List<PushLogEntry> getPushLog(String repositoryName, Repository repository, int offset, int maxCount) {
- return getPushLog(repositoryName, repository, null, offset, maxCount);
+ public static List<RefLogEntry> getRefLog(String repositoryName, Repository repository, int offset, int maxCount) {
+ return getRefLog(repositoryName, repository, null, offset, maxCount);
}
- public static List<PushLogEntry> getPushLog(String repositoryName, Repository repository, Date minimumDate) {
- return getPushLog(repositoryName, repository, minimumDate, 0, -1);
+ public static List<RefLogEntry> getRefLog(String repositoryName, Repository repository, Date minimumDate) {
+ return getRefLog(repositoryName, repository, minimumDate, 0, -1);
}
/**
- * Returns the list of push log entries as they were recorded by Gitblit.
- * Each PushLogEntry may represent multiple ref updates.
+ * Returns the list of reflog entries as they were recorded by Gitblit.
+ * Each RefLogEntry may represent multiple ref updates.
*
* @param repositoryName
* @param repository
@@ -344,10 +367,10 @@ public class PushLogUtils {
* if < 0, all pushes are returned.
* @return a list of push log entries
*/
- public static List<PushLogEntry> getPushLog(String repositoryName, Repository repository,
+ public static List<RefLogEntry> getRefLog(String repositoryName, Repository repository,
Date minimumDate, int offset, int maxCount) {
- List<PushLogEntry> list = new ArrayList<PushLogEntry>();
- RefModel ref = getPushLogBranch(repository);
+ List<RefLogEntry> list = new ArrayList<RefLogEntry>();
+ RefModel ref = getRefLogBranch(repository);
if (ref == null) {
return list;
}
@@ -358,9 +381,9 @@ public class PushLogUtils {
Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
List<RevCommit> pushes;
if (minimumDate == null) {
- pushes = JGitUtils.getRevLog(repository, GB_PUSHES, offset, maxCount);
+ pushes = JGitUtils.getRevLog(repository, GB_REFLOG, offset, maxCount);
} else {
- pushes = JGitUtils.getRevLog(repository, GB_PUSHES, minimumDate);
+ pushes = JGitUtils.getRevLog(repository, GB_REFLOG, minimumDate);
}
for (RevCommit push : pushes) {
if (push.getAuthorIdent().getName().equalsIgnoreCase("gitblit")) {
@@ -371,7 +394,7 @@ public class PushLogUtils {
UserModel user = newUserModelFrom(push.getAuthorIdent());
Date date = push.getAuthorIdent().getWhen();
- PushLogEntry log = new PushLogEntry(repositoryName, date, user);
+ RefLogEntry log = new RefLogEntry(repositoryName, date, user);
list.add(log);
List<PathChangeModel> changedRefs = JGitUtils.getFilesInCommit(repository, push);
for (PathChangeModel change : changedRefs) {
@@ -410,8 +433,8 @@ public class PushLogUtils {
* @param maxCount
* @return a list of push log entries separated by ref
*/
- public static List<PushLogEntry> getPushLogByRef(String repositoryName, Repository repository, int maxCount) {
- return getPushLogByRef(repositoryName, repository, 0, maxCount);
+ public static List<RefLogEntry> getLogByRef(String repositoryName, Repository repository, int maxCount) {
+ return getLogByRef(repositoryName, repository, 0, maxCount);
}
/**
@@ -424,65 +447,65 @@ public class PushLogUtils {
* @param maxCount
* @return a list of push log entries separated by ref
*/
- public static List<PushLogEntry> getPushLogByRef(String repositoryName, Repository repository, int offset,
+ public static List<RefLogEntry> getLogByRef(String repositoryName, Repository repository, int offset,
int maxCount) {
// break the push log into ref push logs and then merge them back into a list
- Map<String, List<PushLogEntry>> refMap = new HashMap<String, List<PushLogEntry>>();
- List<PushLogEntry> pushes = getPushLog(repositoryName, repository, offset, maxCount);
- for (PushLogEntry push : pushes) {
- for (String ref : push.getChangedRefs()) {
+ Map<String, List<RefLogEntry>> refMap = new HashMap<String, List<RefLogEntry>>();
+ List<RefLogEntry> refLog = getRefLog(repositoryName, repository, offset, maxCount);
+ for (RefLogEntry entry : refLog) {
+ for (String ref : entry.getChangedRefs()) {
if (!refMap.containsKey(ref)) {
- refMap.put(ref, new ArrayList<PushLogEntry>());
+ refMap.put(ref, new ArrayList<RefLogEntry>());
}
- // construct new ref-specific push log entry
- PushLogEntry refPush;
- if (push instanceof DailyLogEntry) {
+ // construct new ref-specific ref change entry
+ RefLogEntry refChange;
+ if (entry instanceof DailyLogEntry) {
// simulated push log from commits grouped by date
- refPush = new DailyLogEntry(push.repository, push.date);
+ refChange = new DailyLogEntry(entry.repository, entry.date);
} else {
// real push log entry
- refPush = new PushLogEntry(push.repository, push.date, push.user);
+ refChange = new RefLogEntry(entry.repository, entry.date, entry.user);
}
- refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
- refPush.addCommits(push.getCommits(ref));
- refMap.get(ref).add(refPush);
+ refChange.updateRef(ref, entry.getChangeType(ref), entry.getOldId(ref), entry.getNewId(ref));
+ refChange.addCommits(entry.getCommits(ref));
+ refMap.get(ref).add(refChange);
}
}
- // merge individual ref pushes into master list
- List<PushLogEntry> refPushLog = new ArrayList<PushLogEntry>();
- for (List<PushLogEntry> refPush : refMap.values()) {
- refPushLog.addAll(refPush);
+ // merge individual ref changes into master list
+ List<RefLogEntry> mergedRefLog = new ArrayList<RefLogEntry>();
+ for (List<RefLogEntry> refPush : refMap.values()) {
+ mergedRefLog.addAll(refPush);
}
- // sort ref push log
- Collections.sort(refPushLog);
+ // sort ref log
+ Collections.sort(mergedRefLog);
- return refPushLog;
+ return mergedRefLog;
}
/**
- * Returns the list of pushes separated by ref (e.g. each ref has it's own
- * PushLogEntry object).
+ * Returns the list of ref changes separated by ref (e.g. each ref has it's own
+ * RefLogEntry object).
*
* @param repositoryName
* @param repository
* @param minimumDate
- * @return a list of push log entries separated by ref
+ * @return a list of ref log entries separated by ref
*/
- public static List<PushLogEntry> getPushLogByRef(String repositoryName, Repository repository, Date minimumDate) {
+ public static List<RefLogEntry> getLogByRef(String repositoryName, Repository repository, Date minimumDate) {
// break the push log into ref push logs and then merge them back into a list
- Map<String, List<PushLogEntry>> refMap = new HashMap<String, List<PushLogEntry>>();
- List<PushLogEntry> pushes = getPushLog(repositoryName, repository, minimumDate);
- for (PushLogEntry push : pushes) {
+ Map<String, List<RefLogEntry>> refMap = new HashMap<String, List<RefLogEntry>>();
+ List<RefLogEntry> pushes = getRefLog(repositoryName, repository, minimumDate);
+ for (RefLogEntry push : pushes) {
for (String ref : push.getChangedRefs()) {
if (!refMap.containsKey(ref)) {
- refMap.put(ref, new ArrayList<PushLogEntry>());
+ refMap.put(ref, new ArrayList<RefLogEntry>());
}
// construct new ref-specific push log entry
- PushLogEntry refPush = new PushLogEntry(push.repository, push.date, push.user);
+ RefLogEntry refPush = new RefLogEntry(push.repository, push.date, push.user);
refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
refPush.addCommits(push.getCommits(ref));
refMap.get(ref).add(refPush);
@@ -490,8 +513,8 @@ public class PushLogUtils {
}
// merge individual ref pushes into master list
- List<PushLogEntry> refPushLog = new ArrayList<PushLogEntry>();
- for (List<PushLogEntry> refPush : refMap.values()) {
+ List<RefLogEntry> refPushLog = new ArrayList<RefLogEntry>();
+ for (List<RefLogEntry> refPush : refMap.values()) {
refPushLog.addAll(refPush);
}
@@ -562,7 +585,7 @@ public class PushLogUtils {
Date tagDate = commit.getAuthorIdent().getWhen();
tags.put(dateStr, new DailyLogEntry(repositoryName, tagDate, tagUser));
}
- PushLogEntry tagEntry = tags.get(dateStr);
+ RefLogEntry tagEntry = tags.get(dateStr);
tagEntry.updateRef(ref.getName(), ReceiveCommand.Type.CREATE);
tagEntry.addCommit(ref.getName(), commit);
} else if (ref.getName().startsWith(Constants.R_PULL)) {
@@ -572,7 +595,7 @@ public class PushLogUtils {
Date commitDate = commit.getAuthorIdent().getWhen();
pulls.put(dateStr, new DailyLogEntry(repositoryName, commitDate, commitUser));
}
- PushLogEntry pullEntry = pulls.get(dateStr);
+ RefLogEntry pullEntry = pulls.get(dateStr);
pullEntry.updateRef(ref.getName(), ReceiveCommand.Type.CREATE);
pullEntry.addCommit(ref.getName(), commit);
}
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
index f4180faa..cdae0931 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
+++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.java
@@ -44,18 +44,18 @@ import com.gitblit.wicket.pages.ForksPage;
import com.gitblit.wicket.pages.GitSearchPage;
import com.gitblit.wicket.pages.GravatarProfilePage;
import com.gitblit.wicket.pages.HistoryPage;
-import com.gitblit.wicket.pages.DashboardPage;
import com.gitblit.wicket.pages.LogPage;
import com.gitblit.wicket.pages.LogoutPage;
import com.gitblit.wicket.pages.LuceneSearchPage;
import com.gitblit.wicket.pages.MarkdownPage;
import com.gitblit.wicket.pages.MetricsPage;
+import com.gitblit.wicket.pages.MyDashboardPage;
import com.gitblit.wicket.pages.OverviewPage;
import com.gitblit.wicket.pages.PatchPage;
import com.gitblit.wicket.pages.ProjectPage;
import com.gitblit.wicket.pages.ProjectsPage;
-import com.gitblit.wicket.pages.PushesPage;
import com.gitblit.wicket.pages.RawPage;
+import com.gitblit.wicket.pages.ReflogPage;
import com.gitblit.wicket.pages.RepositoriesPage;
import com.gitblit.wicket.pages.ReviewProposalPage;
import com.gitblit.wicket.pages.SummaryPage;
@@ -69,7 +69,7 @@ import com.gitblit.wicket.pages.UsersPage;
public class GitBlitWebApp extends WebApplication {
- public final static Class<? extends BasePage> HOME_PAGE_CLASS = DashboardPage.class;
+ public final static Class<? extends BasePage> HOME_PAGE_CLASS = MyDashboardPage.class;
@Override
public void init() {
@@ -98,7 +98,7 @@ public class GitBlitWebApp extends WebApplication {
mount("/repositories", RepositoriesPage.class);
mount("/overview", OverviewPage.class, "r", "h");
mount("/summary", SummaryPage.class, "r");
- mount("/pushes", PushesPage.class, "r", "h");
+ mount("/reflog", ReflogPage.class, "r", "h");
mount("/commits", LogPage.class, "r", "h");
mount("/log", LogPage.class, "r", "h");
mount("/tags", TagsPage.class, "r");
diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
index 2e17e605..f7e72ca9 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -462,8 +462,7 @@ gb.to = to
gb.at = at
gb.of = of
gb.in = in
-gb.morePushes = all pushes...
-gb.pushes = pushes
+gb.moreChanges = all changes...
gb.pushedNCommitsTo = pushed {0} commits to
gb.pushedOneCommitTo = pushed 1 commit to
gb.commitsTo = {0} commits to
@@ -488,8 +487,12 @@ gb.stargazers = stargazers
gb.starredRepositories = starred repositories
gb.failedToUpdateUser = Failed to update user account!
gb.myRepositories = my repositories
-gb.noActivity = there has been no recent commit activity
+gb.noActivity = there has been no activity in the last {0} days
gb.findSomeRepositories = find some repositories
gb.metricAuthorExclusions = author metric exclusions
gb.myDashboard = my dashboard
-gb.failedToFindAccount = failed to find user account ''{0}'' \ No newline at end of file
+gb.failedToFindAccount = failed to find user account ''{0}''
+gb.reflog = reflog
+gb.active = active
+gb.starred = starred
+gb.owned = owned \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/DashboardPage.html b/src/main/java/com/gitblit/wicket/pages/DashboardPage.html
deleted file mode 100644
index 1da7ef41..00000000
--- a/src/main/java/com/gitblit/wicket/pages/DashboardPage.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!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:extend>
-<div class="container">
- <div class="hidden-phone markdown" style="padding-bottom:5px;" wicket:id="repositoriesMessage">[repositories message]</div>
-
- <div class="row">
- <div class="span7">
- <div style="color:#888;font-size:1.75em;padding-bottom:5px;" wicket:id="feedheader"></div>
- <div class="hidden-phone hidden-tablet" style="text-align:center;">
- <table>
- <tr>
- <td><div id="chartRepositories" style="display:inline-block;width: 175px; height:175px"></div></td>
- <td><div id="chartAuthors" style="display:inline-block;width: 175px; height: 175px;"></div></td>
- </tr>
- </table>
- </div>
- <div wicket:id="digests"></div>
- </div>
- <div class="span5">
- <div wicket:id="active">[active]</div>
- <div wicket:id="starred">[starred]</div>
- <div wicket:id="owned">[owned]</div>
- </div>
-
- </div>
-</div>
-
-<wicket:fragment wicket:id="starredListFragment">
- <div ng-controller="starredCtrl" style="border: 1px solid #ddd;border-radius: 4px;margin-bottom: 20px;">
- <div class="header" style="padding: 5px;border: none;"><i class="icon-star"></i> <wicket:message key="gb.starredRepositories"></wicket:message> ({{starred.length}})
- <div class="pull-right">
- <a class="btn btn-mini">more</a>
- </div>
- <div style="padding: 5px 0px 0px;">
- <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
- </div>
- </div>
-
- <div ng-repeat="item in starred | limitTo: 20 | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
- <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
- <a href="summary/?r={{item.r}}">{{item.p}}<b>{{item.n}}</b></a>
- <span class="link hidden-tablet hidden-phone" style="color: #aaa;" title="{{item.d}}">{{item.t}}</span>
- <span ng-show="item.s" class="pull-right">
- <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
- </span>
- </div>
-
- </div>
-</wicket:fragment>
-
-<wicket:fragment wicket:id="ownedListFragment">
- <div ng-controller="ownedCtrl" style="border: 1px solid #ddd;border-radius: 4px;">
- <div class="header" style="padding: 5px;border: none;"><i class="icon-user"></i> <wicket:message key="gb.myRepositories"></wicket:message> ({{owned.length}})
- <div class="hidden-phone pull-right">
- <span wicket:id="create"></span>
- </div>
- <div style="padding: 5px 0px 0px;">
- <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
- </div>
- </div>
-
- <div ng-repeat="item in owned | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
- <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
- <a href="summary/?r={{item.r}}">{{item.p}}<b>{{item.n}}</b></a>
- <span class="link hidden-tablet hidden-phone" style="color: #bbb;" title="{{item.d}}">{{item.t}}</span>
- <span ng-show="item.s" class="pull-right">
- <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
- </span>
- </div>
- </div>
-</wicket:fragment>
-
-<wicket:fragment wicket:id="activeListFragment">
- <div ng-controller="activeCtrl" style="border: 1px solid #ddd;border-radius: 4px;margin-bottom: 20px;">
- <div class="header" style="padding: 5px;border: none;"><i class="icon-user"></i> <wicket:message key="gb.activeRepositories"></wicket:message> ({{active.length}})
- <div style="padding: 5px 0px 0px;">
- <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
- </div>
- </div>
-
- <div ng-repeat="item in active | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
- <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
- <a href="summary/?r={{item.r}}">{{item.p}}<b>{{item.n}}</b></a>
- <span class="link hidden-tablet hidden-phone" style="color: #bbb;" title="{{item.d}}">{{item.t}}</span>
- <span ng-show="item.s" class="pull-right">
- <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
- </span>
- </div>
- </div>
-</wicket:fragment>
-
-</wicket:extend>
-</body>
-</html> \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java
index 6c328b10..1c45b64a 100644
--- a/src/main/java/com/gitblit/wicket/pages/DashboardPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/DashboardPage.java
@@ -15,49 +15,40 @@
*/
package com.gitblit.wicket.pages;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
import java.io.Serializable;
import java.text.DateFormat;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
+import java.util.Collection;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.TreeSet;
-import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.panel.Fragment;
-import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Repository;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.models.DailyLogEntry;
import com.gitblit.models.Metric;
-import com.gitblit.models.PushLogEntry;
+import com.gitblit.models.RefLogEntry;
import com.gitblit.models.RepositoryCommit;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
-import com.gitblit.utils.MarkdownUtils;
-import com.gitblit.utils.PushLogUtils;
+import com.gitblit.utils.RefLogUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebApp;
-import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.PageRegistration;
import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
@@ -66,19 +57,17 @@ import com.gitblit.wicket.charting.GoogleChart;
import com.gitblit.wicket.charting.GoogleCharts;
import com.gitblit.wicket.charting.GooglePieChart;
import com.gitblit.wicket.ng.NgController;
+import com.gitblit.wicket.panels.DigestsPanel;
import com.gitblit.wicket.panels.LinkPanel;
-import com.gitblit.wicket.panels.PushesPanel;
-public class DashboardPage extends RootPage {
+public abstract class DashboardPage extends RootPage {
public DashboardPage() {
super();
- setup(null);
}
public DashboardPage(PageParameters params) {
super(params);
- setup(params);
}
@Override
@@ -86,115 +75,50 @@ public class DashboardPage extends RootPage {
return true;
}
- private void setup(PageParameters params) {
- setupPage("", "");
- // check to see if we should display a login message
- boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
- if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
- String messageSource = GitBlit.getString(Keys.web.loginMessage, "gitblit");
- String message = readMarkdown(messageSource, "login.mkd");
- Component repositoriesMessage = new Label("repositoriesMessage", message);
- add(repositoriesMessage.setEscapeModelStrings(false));
- add(new Label("digests"));
- add(new Label("active").setVisible(false));
- add(new Label("starred").setVisible(false));
- add(new Label("owned").setVisible(false));
- add(new Label("feedheader").setVisible(false));
- return;
- }
-
- // Load the markdown welcome message
- String messageSource = GitBlit.getString(Keys.web.repositoriesMessage, "gitblit");
- String message = readMarkdown(messageSource, "welcome.mkd");
- Component repositoriesMessage = new Label("repositoriesMessage", message)
- .setEscapeModelStrings(false).setVisible(message.length() > 0);
- add(repositoriesMessage);
-
- UserModel user = GitBlitWebSession.get().getUser();
- if (user == null) {
- user = UserModel.ANONYMOUS;
- }
-
- Comparator<RepositoryModel> lastUpdateSort = new Comparator<RepositoryModel>() {
- @Override
- public int compare(RepositoryModel o1, RepositoryModel o2) {
- return o2.lastChange.compareTo(o1.lastChange);
- }
- };
-
- // parameters
- int daysBack = params == null ? 0 : WicketUtils.getDaysBack(params);
- if (daysBack < 1) {
- daysBack = 7;
- }
+ protected void addActivity(UserModel user, Collection<RepositoryModel> repositories, int daysBack) {
Calendar c = Calendar.getInstance();
c.add(Calendar.DATE, -1*daysBack);
Date minimumDate = c.getTime();
TimeZone timezone = getTimeZone();
- // build repo lists
- List<RepositoryModel> starred = new ArrayList<RepositoryModel>();
- List<RepositoryModel> owned = new ArrayList<RepositoryModel>();
- List<RepositoryModel> active = new ArrayList<RepositoryModel>();
-
- for (RepositoryModel model : getRepositoryModels()) {
- if (model.isUsersPersonalRepository(user.username) || model.isOwner(user.username)) {
- owned.add(model);
- }
-
- if (user.getPreferences().isStarredRepository(model.name)) {
- starred.add(model);
- }
-
- if (model.isShowActivity() && model.lastChange.after(minimumDate)) {
- active.add(model);
- }
- }
-
- Collections.sort(owned, lastUpdateSort);
- Collections.sort(starred, lastUpdateSort);
- Collections.sort(active, lastUpdateSort);
-
- Set<RepositoryModel> feedSources = new HashSet<RepositoryModel>();
- feedSources.addAll(starred);
- if (feedSources.isEmpty()) {
- feedSources.addAll(active);
- }
-
// create daily commit digest feed
- List<PushLogEntry> pushes = new ArrayList<PushLogEntry>();
- for (RepositoryModel model : feedSources) {
+ List<DailyLogEntry> digests = new ArrayList<DailyLogEntry>();
+ for (RepositoryModel model : repositories) {
Repository repository = GitBlit.self().getRepository(model.name);
- List<DailyLogEntry> entries = PushLogUtils.getDailyLogByRef(model.name, repository, minimumDate, timezone);
- pushes.addAll(entries);
+ List<DailyLogEntry> entries = RefLogUtils.getDailyLogByRef(model.name, repository, minimumDate, timezone);
+ digests.addAll(entries);
repository.close();
}
- if (pushes.size() == 0) {
+ Fragment activityFragment = new Fragment("activity", "activityFragment", this);
+ add(activityFragment);
+ if (digests.size() == 0) {
// quiet or no starred repositories
- if (feedSources.size() == 0) {
+ if (repositories.size() == 0) {
if (UserModel.ANONYMOUS.equals(user)) {
- add(new Label("digests", getString("gb.noActivity")));
+ activityFragment.add(new Label("digests", MessageFormat.format(getString("gb.noActivity"), daysBack)));
} else {
- add(new LinkPanel("digests", null, getString("gb.findSomeRepositories"), RepositoriesPage.class));
+ activityFragment.add(new LinkPanel("digests", null, getString("gb.findSomeRepositories"), RepositoriesPage.class));
}
} else {
- add(new Label("digests", getString("gb.noActivity")));
+ activityFragment.add(new Label("digests", MessageFormat.format(getString("gb.noActivity"), daysBack)));
}
} else {
// show daily commit digest feed
- Collections.sort(pushes);
- add(new PushesPanel("digests", pushes));
+ Collections.sort(digests);
+ DigestsPanel digestsPanel = new DigestsPanel("digests", digests);
+ WicketUtils.setCssStyle(digestsPanel, "margin-top:-20px");
+ activityFragment.add(digestsPanel);
}
// add the nifty charts
- if (!ArrayUtils.isEmpty(pushes)) {
+ if (!ArrayUtils.isEmpty(digests)) {
// aggregate author exclusions
Set<String> authorExclusions = new TreeSet<String>();
for (String author : GitBlit.getStrings(Keys.web.metricAuthorExclusions)) {
authorExclusions.add(author.toLowerCase());
}
- for (RepositoryModel model : feedSources) {
+ for (RepositoryModel model : repositories) {
if (!ArrayUtils.isEmpty(model.metricAuthorExclusions)) {
for (String author : model.metricAuthorExclusions) {
authorExclusions.add(author.toLowerCase());
@@ -202,40 +126,10 @@ public class DashboardPage extends RootPage {
}
}
- addCharts(pushes, authorExclusions, daysBack);
- } else {
- add(new Label("feedheader").setVisible(false));
- }
-
- // active repository list
- if (starred.isEmpty()) {
- Fragment activeView = createNgList("active", "activeListFragment", "activeCtrl", active);
- add(activeView);
+ addCharts(activityFragment, digests, authorExclusions, daysBack);
} else {
- add(new Label("active").setVisible(false));
- }
-
- // starred repository list
- if (ArrayUtils.isEmpty(starred)) {
- add(new Label("starred").setVisible(false));
- } else {
- Fragment starredView = createNgList("starred", "starredListFragment", "starredCtrl", starred);
- add(starredView);
- }
-
- // owned repository list
- if (ArrayUtils.isEmpty(owned)) {
- add(new Label("owned").setVisible(false));
- } else {
- Fragment ownedView = createNgList("owned", "ownedListFragment", "ownedCtrl", owned);
- if (user.canCreate) {
- // create button
- ownedView.add(new LinkPanel("create", "btn btn-mini", getString("gb.newRepository"), EditRepositoryPage.class));
- } else {
- // no button
- ownedView.add(new Label("create").setVisible(false));
- }
- add(ownedView);
+ activityFragment.add(new Label("charts").setVisible(false));
+ activityFragment.add(new Label("feedheader").setVisible(false));
}
}
@@ -259,6 +153,7 @@ public class DashboardPage extends RootPage {
item.n = name;
item.p = path;
item.r = repo.name;
+ item.i = repo.description;
item.s = GitBlit.self().getStarCount(repo);
item.t = getTimeUtils().timeAgo(repo.lastChange);
item.d = df.format(repo.lastChange);
@@ -295,104 +190,32 @@ public class DashboardPage extends RootPage {
pages.add(menu);
}
- private String readMarkdown(String messageSource, String resource) {
- String message = "";
- if (messageSource.equalsIgnoreCase("gitblit")) {
- // Read default message
- message = readDefaultMarkdown(resource);
- } else {
- // Read user-supplied message
- if (!StringUtils.isEmpty(messageSource)) {
- File file = GitBlit.getFileOrFolder(messageSource);
- if (file.exists()) {
- try {
- FileInputStream fis = new FileInputStream(file);
- InputStreamReader reader = new InputStreamReader(fis,
- Constants.CHARACTER_ENCODING);
- message = MarkdownUtils.transformMarkdown(reader);
- reader.close();
- } catch (Throwable t) {
- message = getString("gb.failedToRead") + " " + file;
- warn(message, t);
- }
- } else {
- message = messageSource + " " + getString("gb.isNotValidFile");
- }
- }
- }
- return message;
- }
-
- private String readDefaultMarkdown(String file) {
- String base = file.substring(0, file.lastIndexOf('.'));
- String ext = file.substring(file.lastIndexOf('.'));
- String lc = getLanguageCode();
- String cc = getCountryCode();
-
- // try to read file_en-us.ext, file_en.ext, file.ext
- List<String> files = new ArrayList<String>();
- if (!StringUtils.isEmpty(lc)) {
- if (!StringUtils.isEmpty(cc)) {
- files.add(base + "_" + lc + "-" + cc + ext);
- files.add(base + "_" + lc + "_" + cc + ext);
- }
- files.add(base + "_" + lc + ext);
- }
- files.add(file);
- for (String name : files) {
- String message;
- InputStreamReader reader = null;
- try {
- InputStream is = getClass().getResourceAsStream("/" + name);
- if (is == null) {
- continue;
- }
- reader = new InputStreamReader(is, Constants.CHARACTER_ENCODING);
- message = MarkdownUtils.transformMarkdown(reader);
- reader.close();
- return message;
- } catch (Throwable t) {
- message = MessageFormat.format(getString("gb.failedToReadMessage"), file);
- error(message, t, false);
- return message;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (Exception e) {
- }
- }
- }
- }
- return MessageFormat.format(getString("gb.failedToReadMessage"), file);
- }
-
/**
* Creates the daily activity line chart, the active repositories pie chart,
* and the active authors pie chart
*
- * @param recentPushes
+ * @param recentChanges
* @param authorExclusions
* @param daysBack
*/
- private void addCharts(List<PushLogEntry> recentPushes, Set<String> authorExclusions, int daysBack) {
+ protected void addCharts(Fragment frag, List<DailyLogEntry> recentChanges, Set<String> authorExclusions, int daysBack) {
// activity metrics
Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>();
Map<String, Metric> authorMetrics = new HashMap<String, Metric>();
// aggregate repository and author metrics
int totalCommits = 0;
- for (PushLogEntry push : recentPushes) {
+ for (RefLogEntry change : recentChanges) {
// aggregate repository metrics
- String repository = StringUtils.stripDotGit(push.repository);
+ String repository = StringUtils.stripDotGit(change.repository);
if (!repositoryMetrics.containsKey(repository)) {
repositoryMetrics.put(repository, new Metric(repository));
}
repositoryMetrics.get(repository).count += 1;
- for (RepositoryCommit commit : push.getCommits()) {
+ for (RepositoryCommit commit : change.getCommits()) {
totalCommits++;
String author = StringUtils.removeNewlines(commit.getAuthorIdent().getName());
String authorName = author.toLowerCase();
@@ -406,7 +229,7 @@ public class DashboardPage extends RootPage {
}
}
- add(new Label("feedheader", MessageFormat.format(getString("gb.recentActivityStats"),
+ frag.add(new Label("feedheader", MessageFormat.format(getString("gb.recentActivityStats"),
daysBack, totalCommits, authorMetrics.size())));
// build google charts
@@ -430,10 +253,11 @@ public class DashboardPage extends RootPage {
chart.setShowLegend(false);
charts.addChart(chart);
- add(new HeaderContributor(charts));
+ add(new HeaderContributor(charts));
+ frag.add(new Fragment("charts", "chartsFragment", this));
}
- class RepoListItem implements Serializable {
+ protected class RepoListItem implements Serializable {
private static final long serialVersionUID = 1L;
@@ -442,6 +266,7 @@ public class DashboardPage extends RootPage {
String p; // project/path
String t; // time ago
String d; // last updated
+ String i; // information/description
long s; // stars
String c; // html color
int wc; // working copy, 1 = true
diff --git a/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.html b/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.html
new file mode 100644
index 00000000..6b78b140
--- /dev/null
+++ b/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.html
@@ -0,0 +1,158 @@
+<!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:extend>
+<div class="container">
+
+ <div class="row" style="padding-top:5px;">
+ <div class="span7">
+ <div class="hidden-phone markdown" style="padding-bottom: 30px;" wicket:id="repositoriesMessage">[repositories message]</div>
+ <div wicket:id="activity"></div>
+ </div>
+ <div class="span5">
+ <div wicket:id="repositoryTabs"></div>
+ </div>
+ </div>
+</div>
+
+<wicket:fragment wicket:id="anonymousTabsFragment">
+ <ul class="nav nav-pills">
+ <li class="active"><a href="#recent" data-toggle="tab"><wicket:message key="gb.active">[active]</wicket:message></a></li>
+ <li><a href="#projects" data-toggle="tab"><wicket:message key="gb.projects">[projects]</wicket:message></a></li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" id="recent">
+ <div wicket:id="active">[recently active]</div>
+ </div>
+ <div class="tab-pane" id="projects">
+ <div wicket:id="projectList">[all projects]</div>
+ </div>
+ </div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="authenticatedTabsFragment">
+ <ul class="nav nav-pills">
+ <li class="active"><a href="#starred" data-toggle="tab"><wicket:message key="gb.starred">[starred]</wicket:message></a></li>
+ <li><a href="#owned" data-toggle="tab"><wicket:message key="gb.owned">[owned]</wicket:message></a></li>
+ <li><a href="#recent" data-toggle="tab"><wicket:message key="gb.active">[active]</wicket:message></a></li>
+ <li><a href="#projects" data-toggle="tab"><wicket:message key="gb.projects">[projects]</wicket:message></a></li>
+ </ul>
+ <div class="tab-content">
+ <div class="tab-pane active" id="starred">
+ <div wicket:id="starred">[starred repositories]</div>
+ </div>
+ <div class="tab-pane" id="owned">
+ <div wicket:id="owned">[my repositories]</div>
+ </div>
+ <div class="tab-pane" id="recent">
+ <div wicket:id="active">[recently active]</div>
+ </div>
+ <div class="tab-pane" id="projects">
+ <div wicket:id="projectList">[all projects]</div>
+ </div>
+ </div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="activityFragment">
+ <div class="dashboardTitle"><wicket:message key="gb.recentActivity"></wicket:message> <small><span wicket:id="feedheader"></span></small></div>
+ <div class="hidden-phone hidden-tablet" style="text-align:center;">
+ <div wicket:id="charts"></div>
+ </div>
+ <div wicket:id="digests"></div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="chartsFragment">
+ <table>
+ <tr>
+ <td><div id="chartRepositories" style="display:inline-block;width: 175px; height:175px"></div></td>
+ <td><div id="chartAuthors" style="display:inline-block;width: 175px; height: 175px;"></div></td>
+ </tr>
+ </table>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="starredListFragment">
+ <div ng-controller="starredCtrl" style="border: 1px solid #ddd;border-radius: 4px;margin-bottom: 20px;">
+ <div class="header" style="padding: 5px;border: none;"><i class="icon-star"></i> <wicket:message key="gb.starredRepositories"></wicket:message> ({{starred.length}})
+ <div style="padding: 5px 0px 0px;">
+ <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
+ </div>
+ </div>
+
+ <div ng-repeat="item in starred | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
+ <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
+ <a href="summary/?r={{item.r}}" title="{{item.i}}">{{item.p}}<b>{{item.n}}</b></a>
+ <span class="link hidden-tablet hidden-phone" style="color: #aaa;" title="{{item.d}}">{{item.t}}</span>
+ <span ng-show="item.s" class="pull-right">
+ <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
+ </span>
+ </div>
+
+ </div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="ownedListFragment">
+ <div ng-controller="ownedCtrl" style="border: 1px solid #ddd;border-radius: 4px;">
+ <div class="header" style="padding: 5px;border: none;"><i class="icon-user"></i> <wicket:message key="gb.myRepositories"></wicket:message> ({{owned.length}})
+ <div class="hidden-phone pull-right">
+ <span wicket:id="create"></span>
+ </div>
+ <div style="padding: 5px 0px 0px;">
+ <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
+ </div>
+ </div>
+
+ <div ng-repeat="item in owned | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
+ <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
+ <a href="summary/?r={{item.r}}" title="{{item.i}}">{{item.p}}<b>{{item.n}}</b></a>
+ <span class="link hidden-tablet hidden-phone" style="color: #bbb;" title="{{item.d}}">{{item.t}}</span>
+ <span ng-show="item.s" class="pull-right">
+ <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
+ </span>
+ </div>
+ </div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="activeListFragment">
+ <div ng-controller="activeCtrl" style="border: 1px solid #ddd;border-radius: 4px;margin-bottom: 20px;">
+ <div class="header" style="padding: 5px;border: none;"><i class="icon-user"></i> <wicket:message key="gb.activeRepositories"></wicket:message> ({{active.length}})
+ <div style="padding: 5px 0px 0px;">
+ <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
+ </div>
+ </div>
+
+ <div ng-repeat="item in active | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
+ <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
+ <a href="summary/?r={{item.r}}" title="{{item.i}}">{{item.p}}<b>{{item.n}}</b></a>
+ <span class="link hidden-tablet hidden-phone" style="color: #bbb;" title="{{item.d}}">{{item.t}}</span>
+ <span ng-show="item.s" class="pull-right">
+ <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
+ </span>
+ </div>
+ </div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="projectListFragment">
+ <div ng-controller="projectListCtrl" style="border: 1px solid #ddd;border-radius: 4px;margin-bottom: 20px;">
+ <div class="header" style="padding: 5px;border: none;"><i class="icon-folder-close"></i> <wicket:message key="gb.projects"></wicket:message> ({{projectList.length}})
+ <div style="padding: 5px 0px 0px;">
+ <input type="text" ng-model="query.n" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
+ </div>
+ </div>
+
+ <div ng-repeat="item in projectList | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
+ <a href="project/{{item.p}}" title="{{item.i}}"><b>{{item.n}}</b></a>
+ <span class="link hidden-tablet hidden-phone" style="color: #bbb;" title="{{item.d}}">{{item.t}}</span>
+ <span class="pull-right">
+ <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;" wicket:message="title:gb.repositories">{{item.c | number}}</span>
+ </span>
+ </div>
+ </div>
+</wicket:fragment>
+
+</wicket:extend>
+</body>
+</html> \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java b/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java
new file mode 100644
index 00000000..b0c89b72
--- /dev/null
+++ b/src/main/java/com/gitblit/wicket/pages/MyDashboardPage.java
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2013 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.wicket.pages;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Serializable;
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.wicket.Component;
+import org.apache.wicket.PageParameters;
+import org.apache.wicket.behavior.HeaderContributor;
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.html.panel.Fragment;
+import org.eclipse.jgit.lib.Constants;
+
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
+import com.gitblit.models.ProjectModel;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
+import com.gitblit.utils.ArrayUtils;
+import com.gitblit.utils.MarkdownUtils;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.wicket.GitBlitWebSession;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.ng.NgController;
+import com.gitblit.wicket.panels.LinkPanel;
+
+public class MyDashboardPage extends DashboardPage {
+
+ public MyDashboardPage() {
+ super();
+ setup(null);
+ }
+
+ public MyDashboardPage(PageParameters params) {
+ super(params);
+ setup(params);
+ }
+
+ @Override
+ protected boolean reusePageParameters() {
+ return true;
+ }
+
+ private void setup(PageParameters params) {
+ setupPage("", "");
+ // check to see if we should display a login message
+ boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
+ if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
+ String messageSource = GitBlit.getString(Keys.web.loginMessage, "gitblit");
+ String message = readMarkdown(messageSource, "login.mkd");
+ Component repositoriesMessage = new Label("repositoriesMessage", message);
+ add(repositoriesMessage.setEscapeModelStrings(false));
+ add(new Label("activity").setVisible(false));
+ add(new Label("repositoryTabs").setVisible(false));
+ return;
+ }
+
+ // Load the markdown welcome message
+ String messageSource = GitBlit.getString(Keys.web.repositoriesMessage, "gitblit");
+ String message = readMarkdown(messageSource, "welcome.mkd");
+ Component repositoriesMessage = new Label("repositoriesMessage", message)
+ .setEscapeModelStrings(false).setVisible(message.length() > 0);
+ add(repositoriesMessage);
+
+ UserModel user = GitBlitWebSession.get().getUser();
+ if (user == null) {
+ user = UserModel.ANONYMOUS;
+ }
+
+ // parameters
+ int daysBack = params == null ? 0 : WicketUtils.getDaysBack(params);
+ if (daysBack < 1) {
+ daysBack = 7;
+ }
+ Calendar c = Calendar.getInstance();
+ c.add(Calendar.DATE, -1*daysBack);
+ Date minimumDate = c.getTime();
+
+ // build repo lists
+ List<RepositoryModel> starred = new ArrayList<RepositoryModel>();
+ List<RepositoryModel> owned = new ArrayList<RepositoryModel>();
+ List<RepositoryModel> active = new ArrayList<RepositoryModel>();
+
+ for (RepositoryModel model : getRepositoryModels()) {
+ if (model.isUsersPersonalRepository(user.username) || model.isOwner(user.username)) {
+ owned.add(model);
+ }
+
+ if (user.getPreferences().isStarredRepository(model.name)) {
+ starred.add(model);
+ }
+
+ if (model.isShowActivity() && model.lastChange.after(minimumDate)) {
+ active.add(model);
+ }
+ }
+
+ Comparator<RepositoryModel> lastUpdateSort = new Comparator<RepositoryModel>() {
+ @Override
+ public int compare(RepositoryModel o1, RepositoryModel o2) {
+ return o2.lastChange.compareTo(o1.lastChange);
+ }
+ };
+
+ Collections.sort(owned, lastUpdateSort);
+ Collections.sort(starred, lastUpdateSort);
+ Collections.sort(active, lastUpdateSort);
+
+ Set<RepositoryModel> feed = new HashSet<RepositoryModel>();
+ feed.addAll(starred);
+ feed.addAll(owned);
+ if (feed.isEmpty()) {
+ feed.addAll(active);
+ }
+
+ addActivity(user, feed, daysBack);
+
+ Fragment repositoryTabs;
+ if (UserModel.ANONYMOUS.equals(user)) {
+ repositoryTabs = new Fragment("repositoryTabs", "anonymousTabsFragment", this);
+ } else {
+ repositoryTabs = new Fragment("repositoryTabs", "authenticatedTabsFragment", this);
+ }
+
+ add(repositoryTabs);
+
+ Fragment projectList = createProjectList();
+ repositoryTabs.add(projectList);
+
+ // active repository list
+ if (active.isEmpty()) {
+ repositoryTabs.add(new Label("active").setVisible(false));
+ } else {
+ Fragment activeView = createNgList("active", "activeListFragment", "activeCtrl", active);
+ repositoryTabs.add(activeView);
+ }
+
+ // starred repository list
+ if (ArrayUtils.isEmpty(starred)) {
+ repositoryTabs.add(new Label("starred").setVisible(false));
+ } else {
+ Fragment starredView = createNgList("starred", "starredListFragment", "starredCtrl", starred);
+ repositoryTabs.add(starredView);
+ }
+
+ // owned repository list
+ if (ArrayUtils.isEmpty(owned)) {
+ repositoryTabs.add(new Label("owned").setVisible(false));
+ } else {
+ Fragment ownedView = createNgList("owned", "ownedListFragment", "ownedCtrl", owned);
+ if (user.canCreate) {
+ // create button
+ ownedView.add(new LinkPanel("create", "btn btn-mini", getString("gb.newRepository"), EditRepositoryPage.class));
+ } else {
+ // no button
+ ownedView.add(new Label("create").setVisible(false));
+ }
+ repositoryTabs.add(ownedView);
+ }
+ }
+
+ private String readMarkdown(String messageSource, String resource) {
+ String message = "";
+ if (messageSource.equalsIgnoreCase("gitblit")) {
+ // Read default message
+ message = readDefaultMarkdown(resource);
+ } else {
+ // Read user-supplied message
+ if (!StringUtils.isEmpty(messageSource)) {
+ File file = GitBlit.getFileOrFolder(messageSource);
+ if (file.exists()) {
+ try {
+ FileInputStream fis = new FileInputStream(file);
+ InputStreamReader reader = new InputStreamReader(fis,
+ Constants.CHARACTER_ENCODING);
+ message = MarkdownUtils.transformMarkdown(reader);
+ reader.close();
+ } catch (Throwable t) {
+ message = getString("gb.failedToRead") + " " + file;
+ warn(message, t);
+ }
+ } else {
+ message = messageSource + " " + getString("gb.isNotValidFile");
+ }
+ }
+ }
+ return message;
+ }
+
+ private String readDefaultMarkdown(String file) {
+ String base = file.substring(0, file.lastIndexOf('.'));
+ String ext = file.substring(file.lastIndexOf('.'));
+ String lc = getLanguageCode();
+ String cc = getCountryCode();
+
+ // try to read file_en-us.ext, file_en.ext, file.ext
+ List<String> files = new ArrayList<String>();
+ if (!StringUtils.isEmpty(lc)) {
+ if (!StringUtils.isEmpty(cc)) {
+ files.add(base + "_" + lc + "-" + cc + ext);
+ files.add(base + "_" + lc + "_" + cc + ext);
+ }
+ files.add(base + "_" + lc + ext);
+ }
+ files.add(file);
+
+ for (String name : files) {
+ String message;
+ InputStreamReader reader = null;
+ try {
+ InputStream is = getClass().getResourceAsStream("/" + name);
+ if (is == null) {
+ continue;
+ }
+ reader = new InputStreamReader(is, Constants.CHARACTER_ENCODING);
+ message = MarkdownUtils.transformMarkdown(reader);
+ reader.close();
+ return message;
+ } catch (Throwable t) {
+ message = MessageFormat.format(getString("gb.failedToReadMessage"), file);
+ error(message, t, false);
+ return message;
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Exception e) {
+ }
+ }
+ }
+ }
+ return MessageFormat.format(getString("gb.failedToReadMessage"), file);
+ }
+
+ protected Fragment createProjectList() {
+ String format = GitBlit.getString(Keys.web.datestampShortFormat, "MM/dd/yy");
+ final DateFormat df = new SimpleDateFormat(format);
+ df.setTimeZone(getTimeZone());
+ List<ProjectModel> projects = GitBlit.self().getProjectModels(getRepositoryModels(), false);
+ Collections.sort(projects, new Comparator<ProjectModel>() {
+ @Override
+ public int compare(ProjectModel o1, ProjectModel o2) {
+ return o2.lastChange.compareTo(o1.lastChange);
+ }
+ });
+
+ List<ProjectListItem> list = new ArrayList<ProjectListItem>();
+ for (ProjectModel proj : projects) {
+ if (proj.isUserProject() || proj.repositories.isEmpty()) {
+ // exclude user projects from list
+ continue;
+ }
+ ProjectListItem item = new ProjectListItem();
+ item.p = proj.name;
+ item.n = StringUtils.isEmpty(proj.title) ? proj.name : proj.title;
+ item.i = proj.description;
+ item.t = getTimeUtils().timeAgo(proj.lastChange);
+ item.d = df.format(proj.lastChange);
+ item.c = proj.repositories.size();
+ list.add(item);
+ }
+
+ // inject an AngularJS controller with static data
+ NgController ctrl = new NgController("projectListCtrl");
+ ctrl.addVariable("projectList", list);
+ add(new HeaderContributor(ctrl));
+
+ Fragment fragment = new Fragment("projectList", "projectListFragment", this);
+ return fragment;
+ }
+
+ protected class ProjectListItem implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ String p; // path
+ String n; // name
+ String t; // time ago
+ String d; // last updated
+ String i; // information/description
+ long c; // repository count
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/pages/OverviewPage.html b/src/main/java/com/gitblit/wicket/pages/OverviewPage.html
index 3340e318..995f8df6 100644
--- a/src/main/java/com/gitblit/wicket/pages/OverviewPage.html
+++ b/src/main/java/com/gitblit/wicket/pages/OverviewPage.html
@@ -48,7 +48,7 @@
<div class="span6">
<div class="hidden-tablet" style="padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid #ddd;" wicket:id="repositoryUrlPanel">[repository url panel]</div>
- <div wicket:id="pushesPanel">[pushes panel]</div>
+ <div wicket:id="reflogPanel">[reflog panel]</div>
</div>
</div>
diff --git a/src/main/java/com/gitblit/wicket/pages/OverviewPage.java b/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
index 42d20c5b..88487670 100644
--- a/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/OverviewPage.java
@@ -41,7 +41,7 @@ import com.gitblit.wicket.charting.GoogleCharts;
import com.gitblit.wicket.charting.GoogleLineChart;
import com.gitblit.wicket.panels.BranchesPanel;
import com.gitblit.wicket.panels.LinkPanel;
-import com.gitblit.wicket.panels.PushesPanel;
+import com.gitblit.wicket.panels.ReflogPanel;
import com.gitblit.wicket.panels.RepositoryUrlPanel;
import com.gitblit.wicket.panels.TagsPanel;
@@ -113,9 +113,9 @@ public class OverviewPage extends RepositoryPage {
add(new RepositoryUrlPanel("repositoryUrlPanel", false, user, model));
- int pushCount = GitBlit.getInteger(Keys.web.overviewPushCount, 5);
- PushesPanel pushes = new PushesPanel("pushesPanel", getRepositoryModel(), r, pushCount, 0, false);
- add(pushes);
+ int reflogCount = GitBlit.getInteger(Keys.web.overviewReflogCount, 5);
+ ReflogPanel reflog = new ReflogPanel("reflogPanel", getRepositoryModel(), r, reflogCount, 0);
+ add(reflog);
add(new TagsPanel("tagsPanel", repositoryName, r, numberRefs).hideIfEmpty());
add(new BranchesPanel("branchesPanel", getRepositoryModel(), r, numberRefs, false).hideIfEmpty());
diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectPage.html b/src/main/java/com/gitblit/wicket/pages/ProjectPage.html
index 3b5d4e6a..9fbe1b2d 100644
--- a/src/main/java/com/gitblit/wicket/pages/ProjectPage.html
+++ b/src/main/java/com/gitblit/wicket/pages/ProjectPage.html
@@ -6,66 +6,70 @@
<body>
<wicket:extend>
-
-<div class="container">
- <div class="row">
- <div class="span12">
- <h2><span wicket:id="projectTitle"></span> <small><span wicket:id="projectDescription"></span></small>
- <a class="hidden-phone hidden-tablet brand" style="text-decoration: none;" wicket:id="syndication" wicket:message="title:gb.feed">
- <img style="border:0px;vertical-align:middle;" src="feed_16x16.png"></img>
- </a>
- </h2>
- <div class="markdown" wicket:id="projectMessage">[project message]</div>
- </div>
- </div>
-
- <div class="tabbable">
- <!-- tab titles -->
- <ul class="nav nav-tabs">
- <li class="active"><a href="#repositories" data-toggle="tab"><wicket:message key="gb.repositories"></wicket:message></a></li>
- <li ><a href="#activity" data-toggle="tab"><wicket:message key="gb.activity"></wicket:message></a></li>
- </ul>
-
- <!-- tab content -->
- <div class="tab-content">
-
- <!-- repositories tab -->
- <div class="tab-pane active" id="repositories">
- <!-- markdown -->
- <div class="row">
- <div class="span12">
- <div class="markdown" wicket:id="repositoriesMessage">[repositories message]</div>
+ <div class="container">
+ <div class="row" style="padding-top:5px;">
+ <div class="span12">
+ <div class="dashboardTitle">
+ <span wicket:id="projectTitle"></span>
+ <small><span wicket:id="projectDescription"></span></small>
+
+ <a
+ class="hidden-phone hidden-tablet brand"
+ style="text-decoration: none;" wicket:id="syndication"
+ wicket:message="title:gb.feed"> <img
+ style="border: 0px; vertical-align: middle;" src="feed_16x16.png"></img>
+ </a>
</div>
</div>
- <div class="row">
- <div class="span6" wicket:id="repositoryList">
- <span wicket:id="repository"></span>
- </div>
- </div>
</div>
- <!-- activity tab -->
- <div class="tab-pane" id="activity">
- <div class="pageTitle">
- <h2><wicket:message key="gb.recentActivity"></wicket:message><small> <span class="hidden-phone">/ <span wicket:id="subheader">[days back]</span></span></small></h2>
+ <div class="row">
+ <div class="span7">
+ <div class="markdown" style="padding-bottom: 30px;" wicket:id="projectMessage">[project message]</div>
+ <div wicket:id="activity">[activity panel]</div>
</div>
-
- <div class="hidden-phone" style="height: 155px;text-align: center;">
- <table>
- <tr>
- <td><span class="hidden-tablet" id="chartDaily"></span></td>
- <td><span id="chartRepositories"></span></td>
- <td><span id="chartAuthors"></span></td>
- </tr>
- </table>
+ <div class="span5">
+ <div class="markdown" wicket:id="repositoriesMessage">[repositories message]</div>
+ <div wicket:id="repositoryList">[repository list]</div>
</div>
-
- <div wicket:id="activityPanel">[activity panel]</div>
</div>
-
</div>
+
+<wicket:fragment wicket:id="activityFragment">
+ <div class="dashboardTitle"><wicket:message key="gb.recentActivity"></wicket:message> <small><span wicket:id="feedheader"></span></small></div>
+ <div class="hidden-phone hidden-tablet" style="text-align:center;">
+ <div wicket:id="charts"></div>
</div>
+ <div wicket:id="digests"></div>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="chartsFragment">
+ <table>
+ <tr>
+ <td><div id="chartRepositories" style="display:inline-block;width: 175px; height:175px"></div></td>
+ <td><div id="chartAuthors" style="display:inline-block;width: 175px; height: 175px;"></div></td>
+ </tr>
+ </table>
+</wicket:fragment>
+
+<wicket:fragment wicket:id="repositoryListFragment">
+ <div ng-controller="repositoryListCtrl" style="border: 1px solid #ddd;border-radius: 4px;margin-bottom: 20px;">
+ <div class="header" style="padding: 5px;border: none;"><img style="vertical-align: middle;" src="git-black-16x16.png"/> <wicket:message key="gb.repositories"></wicket:message> ({{repositoryList.length}})
+ <div style="padding: 5px 0px 0px;">
+ <input type="text" ng-model="query.r" class="input-large" wicket:message="placeholder:gb.filter" style="border-radius: 14px; padding: 3px 14px;margin: 0px;"></input>
+ </div>
+ </div>
+
+ <div ng-repeat="item in repositoryList | filter:query" style="padding: 3px;border-top: 1px solid #ddd;">
+ <b><span class="repositorySwatch" style="background-color:{{item.c}};"><span ng-show="item.wc">!</span><span ng-show="!item.wc">&nbsp;</span></span></b>
+ <a href="summary/?r={{item.r}}" title="{{item.i}}">{{item.p}}<b>{{item.n}}</b></a>
+ <span class="link hidden-tablet hidden-phone" style="color: #bbb;" title="{{item.d}}">{{item.t}}</span>
+ <span ng-show="item.s" class="pull-right">
+ <span style="padding: 0px 5px;color: #888;font-weight:bold;vertical-align:middle;">{{item.s | number}} <i style="vertical-align:baseline;" class="iconic-star"></i></span>
+ </span>
+ </div>
</div>
-</wicket:extend>
+</wicket:fragment>
+ </wicket:extend>
</body>
</html> \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectPage.java b/src/main/java/com/gitblit/wicket/pages/ProjectPage.java
index 7eba0331..c64e900a 100644
--- a/src/main/java/com/gitblit/wicket/pages/ProjectPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ProjectPage.java
@@ -15,34 +15,23 @@
*/
package com.gitblit.wicket.pages;
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
-import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.ExternalLink;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.markup.repeater.data.DataView;
-import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.apache.wicket.markup.html.panel.Fragment;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.SyndicationServlet;
-import com.gitblit.models.Activity;
-import com.gitblit.models.Metric;
import com.gitblit.models.ProjectModel;
import com.gitblit.models.RepositoryModel;
-import com.gitblit.utils.ActivityUtils;
+import com.gitblit.models.UserModel;
import com.gitblit.utils.MarkdownUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebApp;
@@ -52,14 +41,8 @@ import com.gitblit.wicket.PageRegistration;
import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.charting.GoogleChart;
-import com.gitblit.wicket.charting.GoogleCharts;
-import com.gitblit.wicket.charting.GoogleLineChart;
-import com.gitblit.wicket.charting.GooglePieChart;
-import com.gitblit.wicket.panels.ActivityPanel;
-import com.gitblit.wicket.panels.ProjectRepositoryPanel;
-public class ProjectPage extends RootPage {
+public class ProjectPage extends DashboardPage {
List<ProjectModel> projectModels = new ArrayList<ProjectModel>();
@@ -72,10 +55,9 @@ public class ProjectPage extends RootPage {
super(params);
setup(params);
}
-
- @Override
- protected boolean reusePageParameters() {
- return true;
+
+ protected Class<? extends BasePage> getRootNavPageClass() {
+ return RepositoriesPage.class;
}
private void setup(PageParameters params) {
@@ -118,8 +100,20 @@ public class ProjectPage extends RootPage {
.setEscapeModelStrings(false).setVisible(rmessage.length() > 0);
add(repositoriesMessage);
- List<RepositoryModel> repositories = getRepositories(params);
+ UserModel user = GitBlitWebSession.get().getUser();
+ if (user == null) {
+ user = UserModel.ANONYMOUS;
+ }
+ int daysBack = params == null ? 0 : WicketUtils.getDaysBack(params);
+ if (daysBack < 1) {
+ daysBack = 7;
+ }
+ // reset the daysback parameter so that we have a complete project
+ // repository list. the recent activity will be built up by the
+ // reflog utils.
+ params.put("db", 0);
+ List<RepositoryModel> repositories = getRepositories(params);
Collections.sort(repositories, new Comparator<RepositoryModel>() {
@Override
public int compare(RepositoryModel o1, RepositoryModel o2) {
@@ -128,145 +122,21 @@ public class ProjectPage extends RootPage {
}
});
- final ListDataProvider<RepositoryModel> dp = new ListDataProvider<RepositoryModel>(repositories);
- DataView<RepositoryModel> dataView = new DataView<RepositoryModel>("repositoryList", dp) {
- private static final long serialVersionUID = 1L;
-
- public void populateItem(final Item<RepositoryModel> item) {
- final RepositoryModel entry = item.getModelObject();
-
- ProjectRepositoryPanel row = new ProjectRepositoryPanel("repository",
- getLocalizer(), this, showAdmin, entry, getAccessRestrictions());
- item.add(row);
- }
- };
- add(dataView);
-
- // project activity
- // parameters
- int daysBack = WicketUtils.getDaysBack(params);
- if (daysBack < 1) {
- daysBack = 14;
- }
- String objectId = WicketUtils.getObject(params);
-
- List<Activity> recentActivity = ActivityUtils.getRecentActivity(repositories,
- daysBack, objectId, getTimeZone());
- if (recentActivity.size() == 0) {
- // no activity, skip graphs and activity panel
- add(new Label("subheader", MessageFormat.format(getString("gb.recentActivityNone"),
- daysBack)));
- add(new Label("activityPanel"));
+
+ addActivity(user, repositories, daysBack);
+
+ if (repositories.isEmpty()) {
+ add(new Label("repositoryList").setVisible(false));
} else {
- // calculate total commits and total authors
- int totalCommits = 0;
- Set<String> uniqueAuthors = new HashSet<String>();
- for (Activity activity : recentActivity) {
- totalCommits += activity.getCommitCount();
- uniqueAuthors.addAll(activity.getAuthorMetrics().keySet());
- }
- int totalAuthors = uniqueAuthors.size();
-
- // add the subheader with stat numbers
- add(new Label("subheader", MessageFormat.format(getString("gb.recentActivityStats"),
- daysBack, totalCommits, totalAuthors)));
-
- // create the activity charts
- GoogleCharts charts = createCharts(recentActivity);
- add(new HeaderContributor(charts));
-
- // add activity panel
- add(new ActivityPanel("activityPanel", recentActivity));
+ Fragment activeView = createNgList("repositoryList", "repositoryListFragment", "repositoryListCtrl", repositories);
+ add(activeView);
}
}
- /**
- * Creates the daily activity line chart, the active repositories pie chart,
- * and the active authors pie chart
- *
- * @param recentActivity
- * @return
- */
- private GoogleCharts createCharts(List<Activity> recentActivity) {
- // activity metrics
- Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>();
- Map<String, Metric> authorMetrics = new HashMap<String, Metric>();
-
- // aggregate repository and author metrics
- for (Activity activity : recentActivity) {
-
- // aggregate author metrics
- for (Map.Entry<String, Metric> entry : activity.getAuthorMetrics().entrySet()) {
- String author = entry.getKey();
- if (!authorMetrics.containsKey(author)) {
- authorMetrics.put(author, new Metric(author));
- }
- authorMetrics.get(author).count += entry.getValue().count;
- }
-
- // aggregate repository metrics
- for (Map.Entry<String, Metric> entry : activity.getRepositoryMetrics().entrySet()) {
- String repository = StringUtils.stripDotGit(entry.getKey());
- if (!repositoryMetrics.containsKey(repository)) {
- repositoryMetrics.put(repository, new Metric(repository));
- }
- repositoryMetrics.get(repository).count += entry.getValue().count;
- }
- }
-
- // build google charts
- int w = 310;
- int h = 150;
- GoogleCharts charts = new GoogleCharts();
-
- // sort in reverse-chronological order and then reverse that
- Collections.sort(recentActivity);
- Collections.reverse(recentActivity);
-
- // daily line chart
- GoogleChart chart = new GoogleLineChart("chartDaily", getString("gb.dailyActivity"), "day",
- getString("gb.commits"));
- SimpleDateFormat df = new SimpleDateFormat("MMM dd");
- df.setTimeZone(getTimeZone());
- for (Activity metric : recentActivity) {
- chart.addValue(df.format(metric.startDate), metric.getCommitCount());
- }
- chart.setWidth(w);
- chart.setHeight(h);
- charts.addChart(chart);
-
- // active repositories pie chart
- chart = new GooglePieChart("chartRepositories", getString("gb.activeRepositories"),
- getString("gb.repository"), getString("gb.commits"));
- for (Metric metric : repositoryMetrics.values()) {
- chart.addValue(metric.name, metric.count);
- }
- chart.setWidth(w);
- chart.setHeight(h);
- charts.addChart(chart);
-
- // active authors pie chart
- chart = new GooglePieChart("chartAuthors", getString("gb.activeAuthors"),
- getString("gb.author"), getString("gb.commits"));
- for (Metric metric : authorMetrics.values()) {
- chart.addValue(metric.name, metric.count);
- }
- chart.setWidth(w);
- chart.setHeight(h);
- charts.addChart(chart);
-
- return charts;
- }
-
@Override
protected void addDropDownMenus(List<PageRegistration> pages) {
PageParameters params = getPageParameters();
- DropDownMenuRegistration projects = new DropDownMenuRegistration("gb.projects",
- ProjectPage.class);
- projects.menuItems.addAll(getProjectsMenu());
- pages.add(0, projects);
-
DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
ProjectPage.class);
// preserve time filter option on repository choices
@@ -277,10 +147,15 @@ public class ProjectPage extends RootPage {
if (menu.menuItems.size() > 0) {
// Reset Filter
- menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
+ menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), "p", WicketUtils.getProjectName(params)));
}
pages.add(menu);
+
+ DropDownMenuRegistration projects = new DropDownMenuRegistration("gb.projects",
+ ProjectPage.class);
+ projects.menuItems.addAll(getProjectsMenu());
+ pages.add(projects);
}
@Override
diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.html b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.html
index caa0f819..2d446ecc 100644
--- a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.html
+++ b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.html
@@ -7,7 +7,6 @@
<body>
<wicket:extend>
<div class="container">
- <div class="markdown" style="padding-bottom:5px;" wicket:id="projectsMessage">[projects message]</div>
<table class="repositories">
<thead>
diff --git a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java
index 7f0b002e..d0001ecb 100644
--- a/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ProjectsPage.java
@@ -15,29 +15,17 @@
*/
package com.gitblit.wicket.pages;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.text.MessageFormat;
-import java.util.ArrayList;
import java.util.List;
-import org.apache.wicket.Component;
import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
-import org.apache.wicket.resource.ContextRelativeResource;
-import org.apache.wicket.util.resource.ResourceStreamNotFoundException;
-import org.eclipse.jgit.lib.Constants;
import com.gitblit.GitBlit;
import com.gitblit.Keys;
import com.gitblit.models.ProjectModel;
-import com.gitblit.utils.MarkdownUtils;
-import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.PageRegistration;
import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
@@ -63,6 +51,11 @@ public class ProjectsPage extends RootPage {
}
@Override
+ protected Class<? extends BasePage> getRootNavPageClass() {
+ return RepositoriesPage.class;
+ }
+
+ @Override
protected List<ProjectModel> getProjectModels() {
return GitBlit.self().getProjectModels(getRepositoryModels(), false);
}
@@ -72,21 +65,10 @@ public class ProjectsPage extends RootPage {
// check to see if we should display a login message
boolean authenticateView = GitBlit.getBoolean(Keys.web.authenticateViewPages, true);
if (authenticateView && !GitBlitWebSession.get().isLoggedIn()) {
- String messageSource = GitBlit.getString(Keys.web.loginMessage, "gitblit");
- String message = readMarkdown(messageSource, "login.mkd");
- Component repositoriesMessage = new Label("projectsMessage", message);
- add(repositoriesMessage.setEscapeModelStrings(false));
add(new Label("projectsPanel"));
return;
}
- // Load the markdown welcome message
- String messageSource = GitBlit.getString(Keys.web.repositoriesMessage, "gitblit");
- String message = readMarkdown(messageSource, "welcome.mkd");
- Component projectsMessage = new Label("projectsMessage", message).setEscapeModelStrings(
- false).setVisible(message.length() > 0);
- add(projectsMessage);
-
List<ProjectModel> projects = getProjects(params);
ListDataProvider<ProjectModel> dp = new ListDataProvider<ProjectModel>(projects);
@@ -130,20 +112,12 @@ public class ProjectsPage extends RootPage {
}
};
add(dataView);
-
- // push the panel down if we are hiding the admin controls and the
- // welcome message
- if (!showAdmin && !projectsMessage.isVisible()) {
- WicketUtils.setCssStyle(dataView, "padding-top:5px;");
- }
}
@Override
protected void addDropDownMenus(List<PageRegistration> pages) {
PageParameters params = getPageParameters();
- pages.add(0, new PageRegistration("gb.projects", ProjectsPage.class, params));
-
DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
ProjectsPage.class);
// preserve time filter option on repository choices
@@ -159,77 +133,4 @@ public class ProjectsPage extends RootPage {
pages.add(menu);
}
-
- private String readMarkdown(String messageSource, String resource) {
- String message = "";
- if (messageSource.equalsIgnoreCase("gitblit")) {
- // Read default message
- message = readDefaultMarkdown(resource);
- } else {
- // Read user-supplied message
- if (!StringUtils.isEmpty(messageSource)) {
- File file = new File(messageSource);
- if (file.exists()) {
- try {
- FileInputStream fis = new FileInputStream(file);
- InputStreamReader reader = new InputStreamReader(fis,
- Constants.CHARACTER_ENCODING);
- message = MarkdownUtils.transformMarkdown(reader);
- reader.close();
- } catch (Throwable t) {
- message = getString("gb.failedToRead") + " " + file;
- warn(message, t);
- }
- } else {
- message = messageSource + " " + getString("gb.isNotValidFile");
- }
- }
- }
- return message;
- }
-
- private String readDefaultMarkdown(String file) {
- String base = file.substring(0, file.lastIndexOf('.'));
- String ext = file.substring(file.lastIndexOf('.'));
- String lc = getLanguageCode();
- String cc = getCountryCode();
-
- // try to read file_en-us.ext, file_en.ext, file.ext
- List<String> files = new ArrayList<String>();
- if (!StringUtils.isEmpty(lc)) {
- if (!StringUtils.isEmpty(cc)) {
- files.add(base + "_" + lc + "-" + cc + ext);
- files.add(base + "_" + lc + "_" + cc + ext);
- }
- files.add(base + "_" + lc + ext);
- }
- files.add(file);
-
- for (String name : files) {
- String message;
- InputStreamReader reader = null;
- try {
- ContextRelativeResource res = WicketUtils.getResource(name);
- InputStream is = res.getResourceStream().getInputStream();
- reader = new InputStreamReader(is, Constants.CHARACTER_ENCODING);
- message = MarkdownUtils.transformMarkdown(reader);
- reader.close();
- return message;
- } catch (ResourceStreamNotFoundException t) {
- continue;
- } catch (Throwable t) {
- message = MessageFormat.format(getString("gb.failedToReadMessage"), file);
- error(message, t, false);
- return message;
- } finally {
- if (reader != null) {
- try {
- reader.close();
- } catch (Exception e) {
- }
- }
- }
- }
- return MessageFormat.format(getString("gb.failedToReadMessage"), file);
- }
}
diff --git a/src/main/java/com/gitblit/wicket/pages/PushesPage.html b/src/main/java/com/gitblit/wicket/pages/ReflogPage.html
index 145db6f5..c0ac7eb7 100644
--- a/src/main/java/com/gitblit/wicket/pages/PushesPage.html
+++ b/src/main/java/com/gitblit/wicket/pages/ReflogPage.html
@@ -12,8 +12,8 @@
<a wicket:id="firstPage"><wicket:message key="gb.pageFirst"></wicket:message></a> | <a wicket:id="prevPage">&laquo; <wicket:message key="gb.pagePrevious"></wicket:message></a> | <a wicket:id="nextPage"><wicket:message key="gb.pageNext"></wicket:message> &raquo;</a>
</div>
- <!-- push log -->
- <div style="margin-top:5px;" wicket:id="pushesPanel">[push log panel]</div>
+ <!-- ref log -->
+ <div style="margin-top:5px;" wicket:id="reflogPanel">[reflog panel]</div>
<!-- pager links -->
<div style="padding-bottom:5px;">
diff --git a/src/main/java/com/gitblit/wicket/pages/PushesPage.java b/src/main/java/com/gitblit/wicket/pages/ReflogPage.java
index 866964ac..884f6167 100644
--- a/src/main/java/com/gitblit/wicket/pages/PushesPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/ReflogPage.java
@@ -19,11 +19,11 @@ import org.apache.wicket.PageParameters;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.panels.PushesPanel;
+import com.gitblit.wicket.panels.ReflogPanel;
-public class PushesPage extends RepositoryPage {
+public class ReflogPage extends RepositoryPage {
- public PushesPage(PageParameters params) {
+ public ReflogPage(PageParameters params) {
super(params);
addSyndicationDiscoveryLink();
@@ -32,24 +32,24 @@ public class PushesPage extends RepositoryPage {
int prevPage = Math.max(0, pageNumber - 1);
int nextPage = pageNumber + 1;
- PushesPanel pushesPanel = new PushesPanel("pushesPanel", getRepositoryModel(), getRepository(), -1,
- pageNumber - 1, false);
- boolean hasMore = pushesPanel.hasMore();
- add(pushesPanel);
+ ReflogPanel reflogPanel = new ReflogPanel("reflogPanel", getRepositoryModel(), getRepository(), -1,
+ pageNumber - 1);
+ boolean hasMore = reflogPanel.hasMore();
+ add(reflogPanel);
- add(new BookmarkablePageLink<Void>("firstPage", PushesPage.class,
+ add(new BookmarkablePageLink<Void>("firstPage", ReflogPage.class,
WicketUtils.newObjectParameter(repositoryName, objectId))
.setEnabled(pageNumber > 1));
- add(new BookmarkablePageLink<Void>("prevPage", PushesPage.class,
+ add(new BookmarkablePageLink<Void>("prevPage", ReflogPage.class,
WicketUtils.newLogPageParameter(repositoryName, objectId, prevPage))
.setEnabled(pageNumber > 1));
- add(new BookmarkablePageLink<Void>("nextPage", PushesPage.class,
+ add(new BookmarkablePageLink<Void>("nextPage", ReflogPage.class,
WicketUtils.newLogPageParameter(repositoryName, objectId, nextPage))
.setEnabled(hasMore));
}
@Override
protected String getPageName() {
- return getString("gb.pushes");
+ return getString("gb.reflog");
}
}
diff --git a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
index a15dd91b..96573012 100644
--- a/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RepositoryPage.java
@@ -60,7 +60,7 @@ import com.gitblit.models.UserRepositoryPreferences;
import com.gitblit.utils.ArrayUtils;
import com.gitblit.utils.DeepCopier;
import com.gitblit.utils.JGitUtils;
-import com.gitblit.utils.PushLogUtils;
+import com.gitblit.utils.RefLogUtils;
import com.gitblit.utils.StringUtils;
import com.gitblit.utils.TicgitUtils;
import com.gitblit.wicket.GitBlitWebSession;
@@ -187,12 +187,12 @@ public abstract class RepositoryPage extends RootPage {
RepositoryModel model = getRepositoryModel();
// standard links
- if (PushLogUtils.getPushLogBranch(r) == null) {
+ if (RefLogUtils.getRefLogBranch(r) == null) {
pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
} else {
pages.put("summary", new PageRegistration("gb.summary", SummaryPage.class, params));
// pages.put("overview", new PageRegistration("gb.overview", OverviewPage.class, params));
- pages.put("pushes", new PageRegistration("gb.pushes", PushesPage.class, params));
+ pages.put("reflog", new PageRegistration("gb.reflog", ReflogPage.class, params));
}
pages.put("commits", new PageRegistration("gb.commits", LogPage.class, params));
pages.put("tree", new PageRegistration("gb.tree", TreePage.class, params));
diff --git a/src/main/java/com/gitblit/wicket/pages/RootPage.java b/src/main/java/com/gitblit/wicket/pages/RootPage.java
index d21be366..8c1a5685 100644
--- a/src/main/java/com/gitblit/wicket/pages/RootPage.java
+++ b/src/main/java/com/gitblit/wicket/pages/RootPage.java
@@ -119,7 +119,7 @@ public abstract class RootPage extends BasePage {
// navigation links
List<PageRegistration> pages = new ArrayList<PageRegistration>();
if (!authenticateView || (authenticateView && GitBlitWebSession.get().isLoggedIn())) {
- pages.add(new PageRegistration(GitBlitWebSession.get().isLoggedIn() ? "gb.myDashboard" : "gb.dashboard", DashboardPage.class,
+ pages.add(new PageRegistration(GitBlitWebSession.get().isLoggedIn() ? "gb.myDashboard" : "gb.dashboard", MyDashboardPage.class,
getRootPageParameters()));
pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class,
getRootPageParameters()));
diff --git a/src/main/java/com/gitblit/wicket/panels/PushesPanel.html b/src/main/java/com/gitblit/wicket/panels/DigestsPanel.html
index fb67cfc1..53a81042 100644
--- a/src/main/java/com/gitblit/wicket/panels/PushesPanel.html
+++ b/src/main/java/com/gitblit/wicket/panels/DigestsPanel.html
@@ -6,15 +6,15 @@
<body>
<wicket:panel>
-<div wicket:id="push" class="push">
+<div wicket:id="change" class="reflog">
<table style="padding: 3px 0px;">
<tr>
- <td class="icon hidden-phone"><i wicket:id="pushIcon"></i></td>
+ <td class="icon hidden-phone"><i wicket:id="changeIcon"></i></td>
<td style="padding-left: 7px;vertical-align:middle;">
<div>
- <span style="color:#aaa;" wicket:id="whenPushed"></span> <span wicket:id="refRewind" class="alert alert-error" style="padding: 1px 5px;font-size: 10px;font-weight: bold;margin-left: 10px;">[rewind]</span>
+ <span class="when" wicket:id="whenChanged"></span>
</div>
- <div style="font-weight:bold;"><span wicket:id="whoPushed">[pusher]</span> <span wicket:id="whatPushed"></span><span wicket:id="refPushed"></span> <span wicket:id="repoPreposition"></span> <span wicket:id="repoPushed"></span> <span wicket:id="byAuthors"></span></div>
+ <div style="font-weight:bold;"><span wicket:id="whoChanged">[who changed]</span> <span wicket:id="whatChanged"></span><span wicket:id="refChanged"></span> <span wicket:id="repoPreposition"></span> <span wicket:id="repoChanged"></span> <span wicket:id="byAuthors"></span></div>
</td>
</tr>
<tr>
@@ -37,7 +37,6 @@
</tr>
</table>
</div>
-<div wicket:id="morePushes">[more...]</div>
</wicket:panel>
</body>
</html> \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java b/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java
new file mode 100644
index 00000000..0f380a49
--- /dev/null
+++ b/src/main/java/com/gitblit/wicket/panels/DigestsPanel.java
@@ -0,0 +1,273 @@
+/*
+ * Copyright 2013 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.wicket.panels;
+
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+import org.apache.wicket.markup.html.basic.Label;
+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.Constants;
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
+import com.gitblit.models.DailyLogEntry;
+import com.gitblit.models.RepositoryCommit;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.TimeUtils;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.ComparePage;
+import com.gitblit.wicket.pages.SummaryPage;
+import com.gitblit.wicket.pages.TagPage;
+import com.gitblit.wicket.pages.TreePage;
+import com.gitblit.wicket.pages.UserPage;
+
+public class DigestsPanel extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private final boolean hasChanges;
+
+ private boolean hasMore;
+
+ public DigestsPanel(String wicketId, List<DailyLogEntry> digests) {
+ super(wicketId);
+ hasChanges = digests.size() > 0;
+
+ final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+
+ String dateFormat = GitBlit.getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
+ final TimeZone timezone = getTimeZone();
+ final DateFormat df = new SimpleDateFormat(dateFormat);
+ df.setTimeZone(timezone);
+ final Calendar cal = Calendar.getInstance(timezone);
+
+ ListDataProvider<DailyLogEntry> dp = new ListDataProvider<DailyLogEntry>(digests);
+ DataView<DailyLogEntry> pushView = new DataView<DailyLogEntry>("change", dp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<DailyLogEntry> logItem) {
+ final DailyLogEntry change = logItem.getModelObject();
+ String fullRefName = change.getChangedRefs().get(0);
+ String shortRefName = fullRefName;
+ boolean isTag = false;
+ if (shortRefName.startsWith(Constants.R_HEADS)) {
+ shortRefName = shortRefName.substring(Constants.R_HEADS.length());
+ } else if (shortRefName.startsWith(Constants.R_TAGS)) {
+ shortRefName = shortRefName.substring(Constants.R_TAGS.length());
+ isTag = true;
+ }
+
+ String fuzzydate;
+ TimeUtils tu = getTimeUtils();
+ Date pushDate = change.date;
+ if (TimeUtils.isToday(pushDate, timezone)) {
+ fuzzydate = tu.today();
+ } else if (TimeUtils.isYesterday(pushDate, timezone)) {
+ fuzzydate = tu.yesterday();
+ } else {
+ // calculate a fuzzy time ago date
+ cal.setTime(pushDate);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ pushDate = cal.getTime();
+ fuzzydate = getTimeUtils().timeAgo(pushDate);
+ }
+ logItem.add(new Label("whenChanged", fuzzydate + ", " + df.format(pushDate)));
+
+ Label changeIcon = new Label("changeIcon");
+ // use the repository hash color to differentiate the icon.
+ String color = StringUtils.getColor(StringUtils.stripDotGit(change.repository));
+ WicketUtils.setCssStyle(changeIcon, "color: " + color);
+
+ if (isTag) {
+ WicketUtils.setCssClass(changeIcon, "iconic-tag");
+ } else {
+ WicketUtils.setCssClass(changeIcon, "iconic-loop");
+ }
+ logItem.add(changeIcon);
+
+ if (!isTag) {
+ logItem.add(new Label("whoChanged").setVisible(false));
+ } else {
+ if (change.user.username.equals(change.user.emailAddress) && change.user.emailAddress.indexOf('@') > -1) {
+ // username is an email address can not link - 1.2.1 push log bug
+ logItem.add(new Label("whoChanged", change.user.getDisplayName()));
+ } else {
+ // link to user account page
+ logItem.add(new LinkPanel("whoChanged", null, change.user.getDisplayName(),
+ UserPage.class, WicketUtils.newUsernameParameter(change.user.username)));
+ }
+ }
+
+ String preposition = "gb.of";
+ boolean isDelete = false;
+ String what;
+ String by = null;
+ switch(change.getChangeType(fullRefName)) {
+ case CREATE:
+ if (isTag) {
+ // new tag
+ what = getString("gb.createdNewTag");
+ preposition = "gb.in";
+ } else {
+ // new branch
+ what = getString("gb.createdNewBranch");
+ preposition = "gb.in";
+ }
+ break;
+ case DELETE:
+ isDelete = true;
+ if (isTag) {
+ what = getString("gb.deletedTag");
+ } else {
+ what = getString("gb.deletedBranch");
+ }
+ preposition = "gb.from";
+ break;
+ default:
+ what = MessageFormat.format(change.getCommitCount() > 1 ? getString("gb.commitsTo") : getString("gb.oneCommitTo"), change.getCommitCount());
+
+ if (change.getAuthorCount() == 1) {
+ by = MessageFormat.format(getString("gb.byOneAuthor"), change.getAuthorIdent().getName());
+ } else {
+ by = MessageFormat.format(getString("gb.byNAuthors"), change.getAuthorCount());
+ }
+ break;
+ }
+ logItem.add(new Label("whatChanged", what));
+ logItem.add(new Label("byAuthors", by).setVisible(!StringUtils.isEmpty(by)));
+
+ if (isDelete) {
+ // can't link to deleted ref
+ logItem.add(new Label("refChanged", shortRefName));
+ } else if (isTag) {
+ // link to tag
+ logItem.add(new LinkPanel("refChanged", null, shortRefName,
+ TagPage.class, WicketUtils.newObjectParameter(change.repository, fullRefName)));
+ } else {
+ // link to tree
+ logItem.add(new LinkPanel("refChanged", null, shortRefName,
+ TreePage.class, WicketUtils.newObjectParameter(change.repository, fullRefName)));
+ }
+
+ // to/from/etc
+ logItem.add(new Label("repoPreposition", getString(preposition)));
+ String repoName = StringUtils.stripDotGit(change.repository);
+ logItem.add(new LinkPanel("repoChanged", null, repoName,
+ SummaryPage.class, WicketUtils.newRepositoryParameter(change.repository)));
+
+ int maxCommitCount = 5;
+ List<RepositoryCommit> commits = change.getCommits();
+ if (commits.size() > maxCommitCount) {
+ commits = new ArrayList<RepositoryCommit>(commits.subList(0, maxCommitCount));
+ }
+
+ // compare link
+ String compareLinkText = null;
+ if ((change.getCommitCount() <= maxCommitCount) && (change.getCommitCount() > 1)) {
+ compareLinkText = MessageFormat.format(getString("gb.viewComparison"), commits.size());
+ } else if (change.getCommitCount() > maxCommitCount) {
+ int diff = change.getCommitCount() - maxCommitCount;
+ compareLinkText = MessageFormat.format(diff > 1 ? getString("gb.nMoreCommits") : getString("gb.oneMoreCommit"), diff);
+ }
+ if (StringUtils.isEmpty(compareLinkText)) {
+ logItem.add(new Label("compareLink").setVisible(false));
+ } else {
+ String endRangeId = change.getNewId(fullRefName);
+ String startRangeId = change.getOldId(fullRefName);
+ logItem.add(new LinkPanel("compareLink", null, compareLinkText, ComparePage.class, WicketUtils.newRangeParameter(change.repository, startRangeId, endRangeId)));
+ }
+
+ final boolean showSwatch = GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);
+
+ ListDataProvider<RepositoryCommit> cdp = new ListDataProvider<RepositoryCommit>(commits);
+ DataView<RepositoryCommit> commitsView = new DataView<RepositoryCommit>("commit", cdp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<RepositoryCommit> commitItem) {
+ final RepositoryCommit commit = commitItem.getModelObject();
+
+ // author gravatar
+ commitItem.add(new GravatarImage("commitAuthor", commit.getAuthorIdent().getName(),
+ commit.getAuthorIdent().getEmailAddress(), null, 16, false, false));
+
+ // merge icon
+ if (commit.getParentCount() > 1) {
+ commitItem.add(WicketUtils.newImage("commitIcon", "commit_merge_16x16.png"));
+ } else {
+ commitItem.add(WicketUtils.newBlankImage("commitIcon"));
+ }
+
+ // short message
+ String shortMessage = commit.getShortMessage();
+ String trimmedMessage = shortMessage;
+ if (commit.getRefs() != null && commit.getRefs().size() > 0) {
+ trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);
+ } else {
+ trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG);
+ }
+ LinkPanel shortlog = new LinkPanel("commitShortMessage", "list",
+ trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(
+ change.repository, commit.getName()));
+ if (!shortMessage.equals(trimmedMessage)) {
+ WicketUtils.setHtmlTooltip(shortlog, shortMessage);
+ }
+ commitItem.add(shortlog);
+
+ // commit hash link
+ LinkPanel commitHash = new LinkPanel("hashLink", null, commit.getName().substring(0, hashLen),
+ CommitPage.class, WicketUtils.newObjectParameter(
+ change.repository, commit.getName()));
+ WicketUtils.setCssClass(commitHash, "shortsha1");
+ WicketUtils.setHtmlTooltip(commitHash, commit.getName());
+ commitItem.add(commitHash);
+
+ if (showSwatch) {
+ // set repository color
+ String color = StringUtils.getColor(StringUtils.stripDotGit(change.repository));
+ WicketUtils.setCssStyle(commitItem, MessageFormat.format("border-left: 2px solid {0};", color));
+ }
+ }
+ };
+
+ logItem.add(commitsView);
+ }
+ };
+
+ add(pushView);
+ }
+
+ public boolean hasMore() {
+ return hasMore;
+ }
+
+ public boolean hideIfEmpty() {
+ setVisible(hasChanges);
+ return hasChanges;
+ }
+}
diff --git a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html
index e9196cda..02d67e30 100644
--- a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html
+++ b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.html
@@ -70,8 +70,6 @@
<wicket:message key="gb.lastChange">[last change]</wicket:message> <span wicket:id="repositoryLastChange">[last change]</span>,
<span style="font-size:0.8em;" wicket:id="repositorySize">[repository size]</span>
</div>
-
- <div class="hidden-phone hidden-tablet" style="padding-top: 5px;" wicket:id="repositoryPrimaryUrl">[repository primary url]</div>
</div>
</div>
</div>
diff --git a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
index e7fe017e..37641d39 100644
--- a/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
+++ b/src/main/java/com/gitblit/wicket/panels/ProjectRepositoryPanel.java
@@ -192,7 +192,5 @@ public class ProjectRepositoryPanel extends BasePanel {
}
add(new ExternalLink("syndication", SyndicationServlet.asLink("", entry.name, null, 0)));
-
- add(new RepositoryUrlPanel("repositoryPrimaryUrl", true, user, entry));
}
}
diff --git a/src/main/java/com/gitblit/wicket/panels/PushesPanel.java b/src/main/java/com/gitblit/wicket/panels/PushesPanel.java
deleted file mode 100644
index 5c473f75..00000000
--- a/src/main/java/com/gitblit/wicket/panels/PushesPanel.java
+++ /dev/null
@@ -1,381 +0,0 @@
-/*
- * Copyright 2013 gitblit.com.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package com.gitblit.wicket.panels;
-
-import java.text.DateFormat;
-import java.text.MessageFormat;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-import java.util.TimeZone;
-
-import org.apache.wicket.markup.html.basic.Label;
-import org.apache.wicket.markup.repeater.Item;
-import org.apache.wicket.markup.repeater.data.DataView;
-import org.apache.wicket.markup.repeater.data.ListDataProvider;
-import org.apache.wicket.model.StringResourceModel;
-import org.eclipse.jgit.lib.Repository;
-
-import com.gitblit.Constants;
-import com.gitblit.GitBlit;
-import com.gitblit.Keys;
-import com.gitblit.models.DailyLogEntry;
-import com.gitblit.models.PushLogEntry;
-import com.gitblit.models.RepositoryCommit;
-import com.gitblit.models.RepositoryModel;
-import com.gitblit.utils.PushLogUtils;
-import com.gitblit.utils.StringUtils;
-import com.gitblit.utils.TimeUtils;
-import com.gitblit.wicket.WicketUtils;
-import com.gitblit.wicket.pages.CommitPage;
-import com.gitblit.wicket.pages.ComparePage;
-import com.gitblit.wicket.pages.PushesPage;
-import com.gitblit.wicket.pages.SummaryPage;
-import com.gitblit.wicket.pages.TagPage;
-import com.gitblit.wicket.pages.TreePage;
-import com.gitblit.wicket.pages.UserPage;
-
-public class PushesPanel extends BasePanel {
-
- private static final long serialVersionUID = 1L;
-
- private final boolean hasPushes;
-
- private boolean hasMore;
-
- public PushesPanel(String wicketId, final RepositoryModel model, Repository r, int limit, int pageOffset, boolean showRepo) {
- super(wicketId);
- boolean pageResults = limit <= 0;
- int pushesPerPage = GitBlit.getInteger(Keys.web.pushesPerPage, 10);
- if (pushesPerPage <= 1) {
- pushesPerPage = 10;
- }
-
- List<PushLogEntry> pushes;
- if (pageResults) {
- pushes = PushLogUtils.getPushLogByRef(model.name, r, pageOffset * pushesPerPage, pushesPerPage);
- } else {
- pushes = PushLogUtils.getPushLogByRef(model.name, r, limit);
- }
-
- // inaccurate way to determine if there are more commits.
- // works unless commits.size() represents the exact end.
- hasMore = pushes.size() >= pushesPerPage;
- hasPushes = pushes.size() > 0;
-
- setup(pushes, showRepo);
-
- // determine to show pager, more, or neither
- if (limit <= 0) {
- // no display limit
- add(new Label("morePushes").setVisible(false));
- } else {
- if (pageResults) {
- // paging
- add(new Label("morePushes").setVisible(false));
- } else {
- // more
- if (pushes.size() == limit) {
- // show more
- add(new LinkPanel("morePushes", "link", new StringResourceModel("gb.morePushes",
- this, null), PushesPage.class,
- WicketUtils.newRepositoryParameter(model.name)));
- } else {
- // no more
- add(new Label("morePushes").setVisible(false));
- }
- }
- }
- }
-
- public PushesPanel(String wicketId, List<PushLogEntry> pushes) {
- super(wicketId);
- hasPushes = pushes.size() > 0;
- setup(pushes, true);
- add(new Label("morePushes").setVisible(false));
- }
-
- protected void setup(List<PushLogEntry> pushes, final boolean showRepo) {
- final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
-
- String dateFormat = GitBlit.getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
- final TimeZone timezone = getTimeZone();
- final DateFormat df = new SimpleDateFormat(dateFormat);
- df.setTimeZone(timezone);
- final Calendar cal = Calendar.getInstance(timezone);
-
- ListDataProvider<PushLogEntry> dp = new ListDataProvider<PushLogEntry>(pushes);
- DataView<PushLogEntry> pushView = new DataView<PushLogEntry>("push", dp) {
- private static final long serialVersionUID = 1L;
-
- public void populateItem(final Item<PushLogEntry> pushItem) {
- final PushLogEntry push = pushItem.getModelObject();
- String fullRefName = push.getChangedRefs().get(0);
- String shortRefName = fullRefName;
- boolean isTag = false;
- boolean isPull = false;
- if (shortRefName.startsWith(Constants.R_HEADS)) {
- shortRefName = shortRefName.substring(Constants.R_HEADS.length());
- } else if (shortRefName.startsWith(Constants.R_TAGS)) {
- shortRefName = shortRefName.substring(Constants.R_TAGS.length());
- isTag = true;
- } else if (shortRefName.startsWith(Constants.R_PULL)) {
- shortRefName = "#" + shortRefName.substring(Constants.R_PULL.length());
- if (shortRefName.endsWith("/head")) {
- // strip pull request head from name
- shortRefName = shortRefName.substring(0, shortRefName.length() - "/head".length());
- }
- isPull = true;
- }
- boolean isDigest = push instanceof DailyLogEntry;
-
- String fuzzydate;
- TimeUtils tu = getTimeUtils();
- Date pushDate = push.date;
- if (TimeUtils.isToday(pushDate, timezone)) {
- fuzzydate = tu.today();
- } else if (TimeUtils.isYesterday(pushDate, timezone)) {
- fuzzydate = tu.yesterday();
- } else {
- // calculate a fuzzy time ago date
- cal.setTime(pushDate);
- cal.set(Calendar.HOUR_OF_DAY, 0);
- cal.set(Calendar.MINUTE, 0);
- cal.set(Calendar.SECOND, 0);
- cal.set(Calendar.MILLISECOND, 0);
- pushDate = cal.getTime();
- fuzzydate = getTimeUtils().timeAgo(pushDate);
- }
- pushItem.add(new Label("whenPushed", fuzzydate + ", " + df.format(pushDate)));
-
- Label pushIcon = new Label("pushIcon");
- if (showRepo) {
- // if we are showing the repo, we are showing multiple
- // repos. use the repository hash color to differentiate
- // the icon.
- String color = StringUtils.getColor(StringUtils.stripDotGit(push.repository));
- WicketUtils.setCssStyle(pushIcon, "color: " + color);
- }
- if (isTag) {
- WicketUtils.setCssClass(pushIcon, "iconic-tag");
- } else if (isPull) {
- WicketUtils.setCssClass(pushIcon, "iconic-share");
- } else if (isDigest) {
- WicketUtils.setCssClass(pushIcon, "iconic-loop");
- } else {
- WicketUtils.setCssClass(pushIcon, "iconic-upload");
- }
- pushItem.add(pushIcon);
-
- if (isDigest && !isTag) {
- pushItem.add(new Label("whoPushed").setVisible(false));
- } else {
- if (push.user.username.equals(push.user.emailAddress) && push.user.emailAddress.indexOf('@') > -1) {
- // username is an email address - 1.2.1 push log bug
- pushItem.add(new Label("whoPushed", push.user.getDisplayName()));
- } else {
- // link to user account page
- pushItem.add(new LinkPanel("whoPushed", null, push.user.getDisplayName(),
- UserPage.class, WicketUtils.newUsernameParameter(push.user.username)));
- }
- }
-
- String preposition = "gb.of";
- boolean isDelete = false;
- boolean isRewind = false;
- String what;
- String by = null;
- switch(push.getChangeType(fullRefName)) {
- case CREATE:
- if (isTag) {
- // new tag
- if (isDigest) {
- what = getString("gb.createdNewTag");
- preposition = "gb.in";
- } else {
- what = getString("gb.pushedNewTag");
- preposition = "gb.to";
- }
- } else if (isPull) {
- // merged pull request
- what = getString("gb.mergedPullRequest");
- preposition = "gb.in";
- } else {
- // new branch
- if (isDigest) {
- what = getString("gb.createdNewBranch");
- preposition = "gb.in";
- } else {
- what = getString("gb.pushedNewBranch");
- preposition = "gb.to";
- }
- }
- break;
- case DELETE:
- isDelete = true;
- if (isTag) {
- what = getString("gb.deletedTag");
- } if (isPull) {
- what = getString("gb.deletedTag");
- } else {
- what = getString("gb.deletedBranch");
- }
- preposition = "gb.from";
- break;
- case UPDATE_NONFASTFORWARD:
- isRewind = true;
- default:
- if (isDigest) {
- what = MessageFormat.format(push.getCommitCount() > 1 ? getString("gb.commitsTo") : getString("gb.oneCommitTo"), push.getCommitCount());
- } else {
- what = MessageFormat.format(push.getCommitCount() > 1 ? getString("gb.pushedNCommitsTo") : getString("gb.pushedOneCommitTo") , push.getCommitCount());
- }
-
- if (push.getAuthorCount() == 1) {
- by = MessageFormat.format(getString("gb.byOneAuthor"), push.getAuthorIdent().getName());
- } else {
- by = MessageFormat.format(getString("gb.byNAuthors"), push.getAuthorCount());
- }
- break;
- }
- pushItem.add(new Label("whatPushed", what));
- pushItem.add(new Label("byAuthors", by).setVisible(!StringUtils.isEmpty(by)));
-
- pushItem.add(new Label("refRewind", getString("gb.rewind")).setVisible(isRewind));
-
- if (isDelete) {
- // can't link to deleted ref
- pushItem.add(new Label("refPushed", shortRefName));
- } else if (isTag) {
- // link to tag
- pushItem.add(new LinkPanel("refPushed", null, shortRefName,
- TagPage.class, WicketUtils.newObjectParameter(push.repository, fullRefName)));
- } else if (isPull) {
- // link to pull request
- pushItem.add(new LinkPanel("refPushed", null, shortRefName,
- TagPage.class, WicketUtils.newObjectParameter(push.repository, fullRefName)));
- } else {
- // link to tree
- pushItem.add(new LinkPanel("refPushed", null, shortRefName,
- TreePage.class, WicketUtils.newObjectParameter(push.repository, fullRefName)));
- }
-
- if (showRepo) {
- // to/from/etc
- pushItem.add(new Label("repoPreposition", getString(preposition)));
-
- String repoName = StringUtils.stripDotGit(push.repository);
- pushItem.add(new LinkPanel("repoPushed", null, repoName,
- SummaryPage.class, WicketUtils.newRepositoryParameter(push.repository)));
- } else {
- // do not display repository name if we are viewing the push
- // log of a repository.
- pushItem.add(new Label("repoPreposition").setVisible(false));
- pushItem.add(new Label("repoPushed").setVisible(false));
- }
-
- int maxCommitCount = 5;
- List<RepositoryCommit> commits = push.getCommits();
- if (commits.size() > maxCommitCount) {
- commits = new ArrayList<RepositoryCommit>(commits.subList(0, maxCommitCount));
- }
-
- // compare link
- String compareLinkText = null;
- if ((push.getCommitCount() <= maxCommitCount) && (push.getCommitCount() > 1)) {
- compareLinkText = MessageFormat.format(getString("gb.viewComparison"), commits.size());
- } else if (push.getCommitCount() > maxCommitCount) {
- int diff = push.getCommitCount() - maxCommitCount;
- compareLinkText = MessageFormat.format(diff > 1 ? getString("gb.nMoreCommits") : getString("gb.oneMoreCommit"), diff);
- }
- if (StringUtils.isEmpty(compareLinkText)) {
- pushItem.add(new Label("compareLink").setVisible(false));
- } else {
- String endRangeId = push.getNewId(fullRefName);
- String startRangeId = push.getOldId(fullRefName);
- pushItem.add(new LinkPanel("compareLink", null, compareLinkText, ComparePage.class, WicketUtils.newRangeParameter(push.repository, startRangeId, endRangeId)));
- }
-
- final boolean showSwatch = showRepo && GitBlit.getBoolean(Keys.web.repositoryListSwatches, true);
-
- ListDataProvider<RepositoryCommit> cdp = new ListDataProvider<RepositoryCommit>(commits);
- DataView<RepositoryCommit> commitsView = new DataView<RepositoryCommit>("commit", cdp) {
- private static final long serialVersionUID = 1L;
-
- public void populateItem(final Item<RepositoryCommit> commitItem) {
- final RepositoryCommit commit = commitItem.getModelObject();
-
- // author gravatar
- commitItem.add(new GravatarImage("commitAuthor", commit.getAuthorIdent().getName(),
- commit.getAuthorIdent().getEmailAddress(), null, 16, false, false));
-
- // merge icon
- if (commit.getParentCount() > 1) {
- commitItem.add(WicketUtils.newImage("commitIcon", "commit_merge_16x16.png"));
- } else {
- commitItem.add(WicketUtils.newBlankImage("commitIcon"));
- }
-
- // short message
- String shortMessage = commit.getShortMessage();
- String trimmedMessage = shortMessage;
- if (commit.getRefs() != null && commit.getRefs().size() > 0) {
- trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);
- } else {
- trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG);
- }
- LinkPanel shortlog = new LinkPanel("commitShortMessage", "list",
- trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(
- push.repository, commit.getName()));
- if (!shortMessage.equals(trimmedMessage)) {
- WicketUtils.setHtmlTooltip(shortlog, shortMessage);
- }
- commitItem.add(shortlog);
-
- // commit hash link
- LinkPanel commitHash = new LinkPanel("hashLink", null, commit.getName().substring(0, hashLen),
- CommitPage.class, WicketUtils.newObjectParameter(
- push.repository, commit.getName()));
- WicketUtils.setCssClass(commitHash, "shortsha1");
- WicketUtils.setHtmlTooltip(commitHash, commit.getName());
- commitItem.add(commitHash);
-
- if (showSwatch) {
- // set repository color
- String color = StringUtils.getColor(StringUtils.stripDotGit(push.repository));
- WicketUtils.setCssStyle(commitItem, MessageFormat.format("border-left: 2px solid {0};", color));
- }
- }
- };
-
- pushItem.add(commitsView);
- }
- };
-
- add(pushView);
- }
-
- public boolean hasMore() {
- return hasMore;
- }
-
- public boolean hideIfEmpty() {
- setVisible(hasPushes);
- return hasPushes;
- }
-}
diff --git a/src/main/java/com/gitblit/wicket/panels/ReflogPanel.html b/src/main/java/com/gitblit/wicket/panels/ReflogPanel.html
new file mode 100644
index 00000000..0148d898
--- /dev/null
+++ b/src/main/java/com/gitblit/wicket/panels/ReflogPanel.html
@@ -0,0 +1,43 @@
+<!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="change" class="reflog">
+ <table style="padding: 3px 0px;">
+ <tr>
+ <td class="icon hidden-phone"><i wicket:id="changeIcon"></i></td>
+ <td style="padding-left: 7px;vertical-align:middle;">
+ <div>
+ <span class="when" wicket:id="whenChanged"></span> <span wicket:id="refRewind" class="alert alert-error" style="padding: 1px 5px;font-size: 10px;font-weight: bold;margin-left: 10px;">[rewind]</span>
+ </div>
+ <div style="font-weight:bold;"><span wicket:id="whoChanged">[change author]</span> <span wicket:id="whatChanged"></span><span wicket:id="refChanged"></span> <span wicket:id="byAuthors"></span></div>
+ </td>
+ </tr>
+ <tr>
+ <td class="hidden-phone"></td>
+ <td style="padding-left: 7px;">
+ <div>
+ <table>
+ <tr wicket:id="commit">
+ <td class="hidden-phone hidden-tablet" style="vertical-align:top;padding-left:7px;"><span wicket:id="commitAuthor"></span></td>
+ <td style="vertical-align:top;"><span wicket:id="hashLink" style="padding-left: 5px;">[hash link]</span></td>
+ <td style="vertical-align:top;padding-left:5px;"><img wicket:id="commitIcon" /></td>
+ <td style="vertical-align:top;">
+ <span wicket:id="commitShortMessage">[commit short message]</span>
+ </td>
+ </tr>
+ </table>
+ <span class="link" wicket:id="compareLink"></span>
+ </div>
+ </td>
+ </tr>
+ </table>
+</div>
+<div wicket:id="moreChanges">[more...]</div>
+</wicket:panel>
+</body>
+</html> \ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java b/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java
new file mode 100644
index 00000000..048ce1b0
--- /dev/null
+++ b/src/main/java/com/gitblit/wicket/panels/ReflogPanel.java
@@ -0,0 +1,305 @@
+/*
+ * Copyright 2013 gitblit.com.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.gitblit.wicket.panels;
+
+import java.text.DateFormat;
+import java.text.MessageFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.TimeZone;
+
+import org.apache.wicket.markup.html.basic.Label;
+import org.apache.wicket.markup.repeater.Item;
+import org.apache.wicket.markup.repeater.data.DataView;
+import org.apache.wicket.markup.repeater.data.ListDataProvider;
+import org.apache.wicket.model.StringResourceModel;
+import org.eclipse.jgit.lib.Repository;
+
+import com.gitblit.Constants;
+import com.gitblit.GitBlit;
+import com.gitblit.Keys;
+import com.gitblit.models.RefLogEntry;
+import com.gitblit.models.RepositoryCommit;
+import com.gitblit.models.RepositoryModel;
+import com.gitblit.utils.RefLogUtils;
+import com.gitblit.utils.StringUtils;
+import com.gitblit.utils.TimeUtils;
+import com.gitblit.wicket.WicketUtils;
+import com.gitblit.wicket.pages.CommitPage;
+import com.gitblit.wicket.pages.ComparePage;
+import com.gitblit.wicket.pages.ReflogPage;
+import com.gitblit.wicket.pages.TagPage;
+import com.gitblit.wicket.pages.TreePage;
+import com.gitblit.wicket.pages.UserPage;
+
+public class ReflogPanel extends BasePanel {
+
+ private static final long serialVersionUID = 1L;
+
+ private final boolean hasChanges;
+
+ private boolean hasMore;
+
+ public ReflogPanel(String wicketId, final RepositoryModel model, Repository r, int limit, int pageOffset) {
+ super(wicketId);
+ boolean pageResults = limit <= 0;
+ int changesPerPage = GitBlit.getInteger(Keys.web.reflogChangesPerPage, 10);
+ if (changesPerPage <= 1) {
+ changesPerPage = 10;
+ }
+
+ List<RefLogEntry> changes;
+ if (pageResults) {
+ changes = RefLogUtils.getLogByRef(model.name, r, pageOffset * changesPerPage, changesPerPage);
+ } else {
+ changes = RefLogUtils.getLogByRef(model.name, r, limit);
+ }
+
+ // inaccurate way to determine if there are more commits.
+ // works unless commits.size() represents the exact end.
+ hasMore = changes.size() >= changesPerPage;
+ hasChanges = changes.size() > 0;
+
+ setup(changes);
+
+ // determine to show pager, more, or neither
+ if (limit <= 0) {
+ // no display limit
+ add(new Label("moreChanges").setVisible(false));
+ } else {
+ if (pageResults) {
+ // paging
+ add(new Label("moreChanges").setVisible(false));
+ } else {
+ // more
+ if (changes.size() == limit) {
+ // show more
+ add(new LinkPanel("moreChanges", "link", new StringResourceModel("gb.moreChanges",
+ this, null), ReflogPage.class,
+ WicketUtils.newRepositoryParameter(model.name)));
+ } else {
+ // no more
+ add(new Label("moreChanges").setVisible(false));
+ }
+ }
+ }
+ }
+
+ public ReflogPanel(String wicketId, List<RefLogEntry> changes) {
+ super(wicketId);
+ hasChanges = changes.size() > 0;
+ setup(changes);
+ add(new Label("moreChanges").setVisible(false));
+ }
+
+ protected void setup(List<RefLogEntry> changes) {
+ final int hashLen = GitBlit.getInteger(Keys.web.shortCommitIdLength, 6);
+
+ String dateFormat = GitBlit.getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
+ final TimeZone timezone = getTimeZone();
+ final DateFormat df = new SimpleDateFormat(dateFormat);
+ df.setTimeZone(timezone);
+ final Calendar cal = Calendar.getInstance(timezone);
+
+ ListDataProvider<RefLogEntry> dp = new ListDataProvider<RefLogEntry>(changes);
+ DataView<RefLogEntry> changeView = new DataView<RefLogEntry>("change", dp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<RefLogEntry> changeItem) {
+ final RefLogEntry change = changeItem.getModelObject();
+ String fullRefName = change.getChangedRefs().get(0);
+ String shortRefName = fullRefName;
+ boolean isTag = false;
+ if (shortRefName.startsWith(Constants.R_HEADS)) {
+ shortRefName = shortRefName.substring(Constants.R_HEADS.length());
+ } else if (shortRefName.startsWith(Constants.R_TAGS)) {
+ shortRefName = shortRefName.substring(Constants.R_TAGS.length());
+ isTag = true;
+ }
+
+ String fuzzydate;
+ TimeUtils tu = getTimeUtils();
+ Date changeDate = change.date;
+ if (TimeUtils.isToday(changeDate, timezone)) {
+ fuzzydate = tu.today();
+ } else if (TimeUtils.isYesterday(changeDate, timezone)) {
+ fuzzydate = tu.yesterday();
+ } else {
+ // calculate a fuzzy time ago date
+ cal.setTime(changeDate);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ changeDate = cal.getTime();
+ fuzzydate = getTimeUtils().timeAgo(changeDate);
+ }
+ changeItem.add(new Label("whenChanged", fuzzydate + ", " + df.format(changeDate)));
+
+ Label changeIcon = new Label("changeIcon");
+ if (isTag) {
+ WicketUtils.setCssClass(changeIcon, "iconic-tag");
+ } else {
+ WicketUtils.setCssClass(changeIcon, "iconic-upload");
+ }
+ changeItem.add(changeIcon);
+
+ if (change.user.username.equals(change.user.emailAddress) && change.user.emailAddress.indexOf('@') > -1) {
+ // username is an email address - 1.2.1 push log bug
+ changeItem.add(new Label("whoChanged", change.user.getDisplayName()));
+ } else {
+ // link to user account page
+ changeItem.add(new LinkPanel("whoChanged", null, change.user.getDisplayName(),
+ UserPage.class, WicketUtils.newUsernameParameter(change.user.username)));
+ }
+
+ boolean isDelete = false;
+ boolean isRewind = false;
+ String what;
+ String by = null;
+ switch(change.getChangeType(fullRefName)) {
+ case CREATE:
+ if (isTag) {
+ // new tag
+ what = getString("gb.pushedNewTag");
+ } else {
+ // new branch
+ what = getString("gb.pushedNewBranch");
+ }
+ break;
+ case DELETE:
+ isDelete = true;
+ if (isTag) {
+ what = getString("gb.deletedTag");
+ } else {
+ what = getString("gb.deletedBranch");
+ }
+ break;
+ case UPDATE_NONFASTFORWARD:
+ isRewind = true;
+ default:
+ what = MessageFormat.format(change.getCommitCount() > 1 ? getString("gb.pushedNCommitsTo") : getString("gb.pushedOneCommitTo") , change.getCommitCount());
+
+ if (change.getAuthorCount() == 1) {
+ by = MessageFormat.format(getString("gb.byOneAuthor"), change.getAuthorIdent().getName());
+ } else {
+ by = MessageFormat.format(getString("gb.byNAuthors"), change.getAuthorCount());
+ }
+ break;
+ }
+ changeItem.add(new Label("whatChanged", what));
+ changeItem.add(new Label("byAuthors", by).setVisible(!StringUtils.isEmpty(by)));
+
+ changeItem.add(new Label("refRewind", getString("gb.rewind")).setVisible(isRewind));
+
+ if (isDelete) {
+ // can't link to deleted ref
+ changeItem.add(new Label("refChanged", shortRefName));
+ } else if (isTag) {
+ // link to tag
+ changeItem.add(new LinkPanel("refChanged", null, shortRefName,
+ TagPage.class, WicketUtils.newObjectParameter(change.repository, fullRefName)));
+ } else {
+ // link to tree
+ changeItem.add(new LinkPanel("refChanged", null, shortRefName,
+ TreePage.class, WicketUtils.newObjectParameter(change.repository, fullRefName)));
+ }
+
+ int maxCommitCount = 5;
+ List<RepositoryCommit> commits = change.getCommits();
+ if (commits.size() > maxCommitCount) {
+ commits = new ArrayList<RepositoryCommit>(commits.subList(0, maxCommitCount));
+ }
+
+ // compare link
+ String compareLinkText = null;
+ if ((change.getCommitCount() <= maxCommitCount) && (change.getCommitCount() > 1)) {
+ compareLinkText = MessageFormat.format(getString("gb.viewComparison"), commits.size());
+ } else if (change.getCommitCount() > maxCommitCount) {
+ int diff = change.getCommitCount() - maxCommitCount;
+ compareLinkText = MessageFormat.format(diff > 1 ? getString("gb.nMoreCommits") : getString("gb.oneMoreCommit"), diff);
+ }
+ if (StringUtils.isEmpty(compareLinkText)) {
+ changeItem.add(new Label("compareLink").setVisible(false));
+ } else {
+ String endRangeId = change.getNewId(fullRefName);
+ String startRangeId = change.getOldId(fullRefName);
+ changeItem.add(new LinkPanel("compareLink", null, compareLinkText, ComparePage.class, WicketUtils.newRangeParameter(change.repository, startRangeId, endRangeId)));
+ }
+
+ ListDataProvider<RepositoryCommit> cdp = new ListDataProvider<RepositoryCommit>(commits);
+ DataView<RepositoryCommit> commitsView = new DataView<RepositoryCommit>("commit", cdp) {
+ private static final long serialVersionUID = 1L;
+
+ public void populateItem(final Item<RepositoryCommit> commitItem) {
+ final RepositoryCommit commit = commitItem.getModelObject();
+
+ // author gravatar
+ commitItem.add(new GravatarImage("commitAuthor", commit.getAuthorIdent().getName(),
+ commit.getAuthorIdent().getEmailAddress(), null, 16, false, false));
+
+ // merge icon
+ if (commit.getParentCount() > 1) {
+ commitItem.add(WicketUtils.newImage("commitIcon", "commit_merge_16x16.png"));
+ } else {
+ commitItem.add(WicketUtils.newBlankImage("commitIcon"));
+ }
+
+ // short message
+ String shortMessage = commit.getShortMessage();
+ String trimmedMessage = shortMessage;
+ if (commit.getRefs() != null && commit.getRefs().size() > 0) {
+ trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG_REFS);
+ } else {
+ trimmedMessage = StringUtils.trimString(shortMessage, Constants.LEN_SHORTLOG);
+ }
+ LinkPanel shortlog = new LinkPanel("commitShortMessage", "list",
+ trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(
+ change.repository, commit.getName()));
+ if (!shortMessage.equals(trimmedMessage)) {
+ WicketUtils.setHtmlTooltip(shortlog, shortMessage);
+ }
+ commitItem.add(shortlog);
+
+ // commit hash link
+ LinkPanel commitHash = new LinkPanel("hashLink", null, commit.getName().substring(0, hashLen),
+ CommitPage.class, WicketUtils.newObjectParameter(
+ change.repository, commit.getName()));
+ WicketUtils.setCssClass(commitHash, "shortsha1");
+ WicketUtils.setHtmlTooltip(commitHash, commit.getName());
+ commitItem.add(commitHash);
+ }
+ };
+
+ changeItem.add(commitsView);
+ }
+ };
+
+ add(changeView);
+ }
+
+ public boolean hasMore() {
+ return hasMore;
+ }
+
+ public boolean hideIfEmpty() {
+ setVisible(hasChanges);
+ return hasChanges;
+ }
+}
diff --git a/src/main/resources/gitblit.css b/src/main/resources/gitblit.css
index 351d43fe..6074b369 100644
--- a/src/main/resources/gitblit.css
+++ b/src/main/resources/gitblit.css
@@ -129,23 +129,39 @@ navbar div>ul .menu-dropdown li a:hover,.nav .menu-dropdown li a:hover,.navbar d
background-color: #002060;
}
-div.push {
+div.reflog {
border-bottom: 1px solid #ddd;
margin-bottom: 5px;
padding-bottom: 5px;
}
-div.push .icon {
+div.reflog .icon {
font-size: 42px;
line-height: 42px;
}
-div.push i {
+div.reflog .when {
+ color: #aaa;
+}
+
+div.reflog i {
font-size: 42px;
color: #bbb;
vertical-align: middle;
}
+div.dashboardTitle {
+ font-size: 1.75em;
+ padding-bottom: 5px;
+ margin-bottom: 10px;
+ border-bottom: 1px solid #ccc;
+}
+
+div.dashboardTitle small {
+ color: #888;
+ font-size: 0.7em;
+}
+
.repositorynavbar {
background-color: #fbfbfb;
border-bottom: 1px solid #ccc;