summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/gitblit/models/Activity.java169
-rw-r--r--src/com/gitblit/models/DailyActivity.java47
-rw-r--r--src/com/gitblit/models/RepositoryCommit.java86
-rw-r--r--src/com/gitblit/utils/ActivityUtils.java130
-rw-r--r--src/com/gitblit/wicket/GitBlitWebApp.properties3
-rw-r--r--src/com/gitblit/wicket/WicketUtils.java23
-rw-r--r--src/com/gitblit/wicket/charting/GoogleCharts.java4
-rw-r--r--src/com/gitblit/wicket/charting/GooglePieChart.java14
-rw-r--r--src/com/gitblit/wicket/pages/ActivityPage.html2
-rw-r--r--src/com/gitblit/wicket/pages/ActivityPage.java187
-rw-r--r--src/com/gitblit/wicket/panels/ActivityPanel.html4
-rw-r--r--src/com/gitblit/wicket/panels/ActivityPanel.java32
12 files changed, 422 insertions, 279 deletions
diff --git a/src/com/gitblit/models/Activity.java b/src/com/gitblit/models/Activity.java
new file mode 100644
index 00000000..f24a5abe
--- /dev/null
+++ b/src/com/gitblit/models/Activity.java
@@ -0,0 +1,169 @@
+/*
+ * Copyright 2011 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.models;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.utils.TimeUtils;
+
+/**
+ * Model class to represent the commit activity across many repositories. This
+ * class is used by the Activity page.
+ *
+ * @author James Moger
+ */
+public class Activity implements Serializable, Comparable<Activity> {
+
+ private static final long serialVersionUID = 1L;
+
+ public final Date startDate;
+
+ public final Date endDate;
+
+ public final List<RepositoryCommit> commits;
+
+ private final Map<String, Metric> authorMetrics;
+
+ private final Map<String, Metric> repositoryMetrics;
+
+ /**
+ * Constructor for one day of activity.
+ *
+ * @param date
+ */
+ public Activity(Date date) {
+ this(date, TimeUtils.ONEDAY - 1);
+ }
+
+ /**
+ * Constructor for specified duration of activity from start date.
+ *
+ * @param date
+ * the start date of the activity
+ * @param duration
+ * the duration of the period in milliseconds
+ */
+ public Activity(Date date, long duration) {
+ startDate = date;
+ endDate = new Date(date.getTime() + duration);
+ commits = new ArrayList<RepositoryCommit>();
+ authorMetrics = new HashMap<String, Metric>();
+ repositoryMetrics = new HashMap<String, Metric>();
+ }
+
+ public RepositoryCommit addCommit(String repository, String branch, RevCommit commit) {
+ RepositoryCommit commitModel = new RepositoryCommit(repository, branch, commit);
+ commits.add(commitModel);
+
+ if (!repositoryMetrics.containsKey(repository)) {
+ repositoryMetrics.put(repository, new Metric(repository));
+ }
+ repositoryMetrics.get(repository).count++;
+
+ String author = commit.getAuthorIdent().getEmailAddress().toLowerCase();
+ if (!authorMetrics.containsKey(author)) {
+ authorMetrics.put(author, new Metric(author));
+ }
+ authorMetrics.get(author).count++;
+ return commitModel;
+ }
+
+ public Map<String, Metric> getAuthorMetrics() {
+ return authorMetrics;
+ }
+
+ public Map<String, Metric> getRepositoryMetrics() {
+ return repositoryMetrics;
+ }
+
+ @Override
+ public int compareTo(Activity o) {
+ // reverse chronological order
+ return o.startDate.compareTo(startDate);
+ }
+
+ /**
+ * Model class to represent a RevCommit, it's source repository, and the
+ * branch. This class is used by the activity page.
+ *
+ * @author James Moger
+ */
+ public static class RepositoryCommit implements Serializable, Comparable<RepositoryCommit> {
+
+ private static final long serialVersionUID = 1L;
+
+ public final String repository;
+
+ public final String branch;
+
+ private final RevCommit commit;
+
+ private List<RefModel> refs;
+
+ public RepositoryCommit(String repository, String branch, RevCommit commit) {
+ this.repository = repository;
+ this.branch = branch;
+ this.commit = commit;
+ }
+
+ public void setRefs(List<RefModel> refs) {
+ this.refs = refs;
+ }
+
+ public List<RefModel> getRefs() {
+ return refs;
+ }
+
+ public String getName() {
+ return commit.getName();
+ }
+
+ public String getShortName() {
+ return commit.getName().substring(0, 8);
+ }
+
+ public String getShortMessage() {
+ return commit.getShortMessage();
+ }
+
+ public int getParentCount() {
+ return commit.getParentCount();
+ }
+
+ public PersonIdent getAuthorIdent() {
+ return commit.getAuthorIdent();
+ }
+
+ @Override
+ public int compareTo(RepositoryCommit o) {
+ // reverse-chronological order
+ if (commit.getCommitTime() > o.commit.getCommitTime()) {
+ return -1;
+ } else if (commit.getCommitTime() < o.commit.getCommitTime()) {
+ return 1;
+ }
+ return 0;
+ }
+ }
+}
diff --git a/src/com/gitblit/models/DailyActivity.java b/src/com/gitblit/models/DailyActivity.java
deleted file mode 100644
index f2e816cb..00000000
--- a/src/com/gitblit/models/DailyActivity.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011 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.models;
-
-import java.io.Serializable;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * Model class to represent the commit activity across many repositories. This
- * class is used by the Activity page.
- *
- * @author James Moger
- */
-public class DailyActivity implements Serializable, Comparable<DailyActivity> {
-
- private static final long serialVersionUID = 1L;
-
- public final Date date;
-
- public final List<RepositoryCommit> commits;
-
- public DailyActivity(Date date) {
- this.date = date;
- commits = new ArrayList<RepositoryCommit>();
- }
-
- @Override
- public int compareTo(DailyActivity o) {
- // reverse chronological order
- return o.date.compareTo(date);
- }
-}
diff --git a/src/com/gitblit/models/RepositoryCommit.java b/src/com/gitblit/models/RepositoryCommit.java
deleted file mode 100644
index 8f5b2bd0..00000000
--- a/src/com/gitblit/models/RepositoryCommit.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright 2011 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.models;
-
-import java.io.Serializable;
-import java.util.List;
-
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.revwalk.RevCommit;
-
-/**
- * Model class to represent a RevCommit, it's source repository, and the branch.
- * This class is used by the activity page.
- *
- * @author James Moger
- */
-public class RepositoryCommit implements Serializable, Comparable<RepositoryCommit> {
-
- private static final long serialVersionUID = 1L;
-
- public final String repository;
-
- public final String branch;
-
- private final RevCommit commit;
-
- private List<RefModel> refs;
-
- public RepositoryCommit(String repository, String branch, RevCommit commit) {
- this.repository = repository;
- this.branch = branch;
- this.commit = commit;
- }
-
- public void setRefs(List<RefModel> refs) {
- this.refs = refs;
- }
-
- public List<RefModel> getRefs() {
- return refs;
- }
-
- public String getName() {
- return commit.getName();
- }
-
- public String getShortName() {
- return commit.getName().substring(0, 8);
- }
-
- public String getShortMessage() {
- return commit.getShortMessage();
- }
-
- public int getParentCount() {
- return commit.getParentCount();
- }
-
- public PersonIdent getAuthorIdent() {
- return commit.getAuthorIdent();
- }
-
- @Override
- public int compareTo(RepositoryCommit o) {
- // reverse-chronological order
- if (commit.getCommitTime() > o.commit.getCommitTime()) {
- return -1;
- } else if (commit.getCommitTime() < o.commit.getCommitTime()) {
- return 1;
- }
- return 0;
- }
-} \ No newline at end of file
diff --git a/src/com/gitblit/utils/ActivityUtils.java b/src/com/gitblit/utils/ActivityUtils.java
new file mode 100644
index 00000000..8c8a7ec2
--- /dev/null
+++ b/src/com/gitblit/utils/ActivityUtils.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2011 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.utils;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.revwalk.RevCommit;
+
+import com.gitblit.GitBlit;
+import com.gitblit.models.Activity;
+import com.gitblit.models.Activity.RepositoryCommit;
+import com.gitblit.models.RefModel;
+import com.gitblit.models.RepositoryModel;
+
+/**
+ * Utility class for building activity information from repositories.
+ *
+ * @author James Moger
+ *
+ */
+public class ActivityUtils {
+
+ /**
+ * Gets the recent activity from the repositories for the last daysBack days
+ * on the specified branch.
+ *
+ * @param models
+ * the list of repositories to query
+ * @param daysBack
+ * the number of days back from Now to collect
+ * @param objectId
+ * the branch to retrieve. If this value is null the default
+ * branch of the repository is used.
+ * @return
+ */
+ public static List<Activity> getRecentActivity(List<RepositoryModel> models, int daysBack,
+ String objectId) {
+
+ // Activity panel shows last daysBack of activity across all
+ // repositories.
+ Date thresholdDate = new Date(System.currentTimeMillis() - daysBack * TimeUtils.ONEDAY);
+
+ // Build a map of DailyActivity from the available repositories for the
+ // specified threshold date.
+ DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
+ Calendar cal = Calendar.getInstance();
+
+ Map<String, Activity> activity = new HashMap<String, Activity>();
+ for (RepositoryModel model : models) {
+ if (model.hasCommits && model.lastChange.after(thresholdDate)) {
+ Repository repository = GitBlit.self().getRepository(model.name);
+ List<RevCommit> commits = JGitUtils.getRevLog(repository, objectId, thresholdDate);
+ Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
+ repository.close();
+
+ // determine commit branch
+ String branch = objectId;
+ if (StringUtils.isEmpty(branch)) {
+ List<RefModel> headRefs = allRefs.get(commits.get(0).getId());
+ List<String> localBranches = new ArrayList<String>();
+ for (RefModel ref : headRefs) {
+ if (ref.getName().startsWith(Constants.R_HEADS)) {
+ localBranches.add(ref.getName().substring(Constants.R_HEADS.length()));
+ }
+ }
+ // determine branch
+ if (localBranches.size() == 1) {
+ // only one branch, choose it
+ branch = localBranches.get(0);
+ } else if (localBranches.size() > 1) {
+ if (localBranches.contains("master")) {
+ // choose master
+ branch = "master";
+ } else {
+ // choose first branch
+ branch = localBranches.get(0);
+ }
+ }
+ }
+
+ for (RevCommit commit : commits) {
+ Date date = JGitUtils.getCommitDate(commit);
+ String dateStr = df.format(date);
+ if (!activity.containsKey(dateStr)) {
+ // Normalize the date to midnight
+ cal.setTime(date);
+ cal.set(Calendar.HOUR_OF_DAY, 0);
+ cal.set(Calendar.MINUTE, 0);
+ cal.set(Calendar.SECOND, 0);
+ cal.set(Calendar.MILLISECOND, 0);
+ activity.put(dateStr, new Activity(cal.getTime()));
+ }
+ RepositoryCommit commitModel = activity.get(dateStr).addCommit(model.name,
+ branch, commit);
+ commitModel.setRefs(allRefs.get(commit.getId()));
+ }
+ }
+ }
+
+ List<Activity> recentActivity = new ArrayList<Activity>(activity.values());
+ for (Activity daily : recentActivity) {
+ Collections.sort(daily.commits);
+ }
+ return recentActivity;
+ }
+}
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index f157a7e5..7ffdb596 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -182,7 +182,8 @@ gb.subscribe = subscribe
gb.branch = branch
gb.maxHits = max hits
gb.recentActivity = recent activity
-gb.recentActivitySubheader = last {0} days / {1} commits by {2} authors
+gb.recentActivityStats = last {0} days / {1} commits by {2} authors
+gb.recentActivityNone = last {0} days / none
gb.dailyActivity = daily activity
gb.activeRepositories = active repositories
gb.activeAuthors = active authors
diff --git a/src/com/gitblit/wicket/WicketUtils.java b/src/com/gitblit/wicket/WicketUtils.java
index 6157a44f..0a207189 100644
--- a/src/com/gitblit/wicket/WicketUtils.java
+++ b/src/com/gitblit/wicket/WicketUtils.java
@@ -16,6 +16,7 @@
package com.gitblit.wicket;
import java.text.DateFormat;
+import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
@@ -59,6 +60,12 @@ public class WicketUtils {
container.add(new SimpleAttributeModifier("style", value));
}
+ public static void setCssBackground(Component container, String value) {
+ String background = MessageFormat.format("background-color:{0};",
+ StringUtils.getColor(value));
+ container.add(new SimpleAttributeModifier("style", background));
+ }
+
public static void setHtmlTooltip(Component container, String value) {
container.add(new SimpleAttributeModifier("title", value));
}
@@ -129,7 +136,7 @@ public class WicketUtils {
filename = "bullet_white.png";
break;
case PENDING:
- case NOCHANGE:
+ case NOCHANGE:
default:
filename = "bullet_black.png";
}
@@ -239,11 +246,11 @@ public class WicketUtils {
}
});
}
-
+
public static PageParameters newTokenParameter(String token) {
return new PageParameters("t=" + token);
}
-
+
public static PageParameters newRegistrationParameter(String url, String name) {
return new PageParameters("u=" + url + ",n=" + name);
}
@@ -297,8 +304,8 @@ public class WicketUtils {
if (StringUtils.isEmpty(objectId)) {
return new PageParameters("r=" + repositoryName + ",f=" + path + ",pg=" + pageNumber);
}
- return new PageParameters("r=" + repositoryName + ",h=" + objectId + ",f=" + path
- + ",pg=" + pageNumber);
+ return new PageParameters("r=" + repositoryName + ",h=" + objectId + ",f=" + path + ",pg="
+ + pageNumber);
}
public static PageParameters newBlobDiffParameter(String repositoryName, String baseCommitId,
@@ -373,7 +380,7 @@ public class WicketUtils {
public static String getToken(PageParameters params) {
return params.getString("t", "");
}
-
+
public static String getUrlParameter(PageParameters params) {
return params.getString("u", "");
}
@@ -411,7 +418,7 @@ public class WicketUtils {
}
return label;
}
-
+
public static Label createTimeLabel(String wicketId, Date date, TimeZone timeZone) {
String format = GitBlit.getString(Keys.web.timeFormat, "HH:mm");
DateFormat df = new SimpleDateFormat(format);
@@ -432,7 +439,7 @@ public class WicketUtils {
}
return label;
}
-
+
public static Label createDatestampLabel(String wicketId, Date date, TimeZone timeZone) {
String format = GitBlit.getString(Keys.web.datestampLongFormat, "EEEE, MMMM d, yyyy");
DateFormat df = new SimpleDateFormat(format);
diff --git a/src/com/gitblit/wicket/charting/GoogleCharts.java b/src/com/gitblit/wicket/charting/GoogleCharts.java
index 9e1572ea..77c522b5 100644
--- a/src/com/gitblit/wicket/charting/GoogleCharts.java
+++ b/src/com/gitblit/wicket/charting/GoogleCharts.java
@@ -1,5 +1,5 @@
/*
- Copyright 2011 comSysto GmbH
+ Copyright 2011 gitblit.com.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -34,7 +34,7 @@ public class GoogleCharts implements IHeaderContributor {
private static final long serialVersionUID = 1L;
- private List<GoogleChart> charts = new ArrayList<GoogleChart>();
+ public final List<GoogleChart> charts = new ArrayList<GoogleChart>();
public void addChart(GoogleChart chart) {
charts.add(chart);
diff --git a/src/com/gitblit/wicket/charting/GooglePieChart.java b/src/com/gitblit/wicket/charting/GooglePieChart.java
index 8367c423..119a8248 100644
--- a/src/com/gitblit/wicket/charting/GooglePieChart.java
+++ b/src/com/gitblit/wicket/charting/GooglePieChart.java
@@ -18,6 +18,8 @@ package com.gitblit.wicket.charting;
import java.text.MessageFormat;
import java.util.Collections;
+import com.gitblit.utils.StringUtils;
+
/**
* Builds an interactive pie chart using the Visualization API.
*
@@ -43,13 +45,21 @@ public class GooglePieChart extends GoogleChart {
Collections.sort(values);
+ StringBuilder colors = new StringBuilder("colors:[");
for (int i = 0; i < values.size(); i++) {
ChartValue value = values.get(i);
+ colors.append('\'');
+ colors.append(StringUtils.getColor(value.name));
+ colors.append('\'');
+ if (i < values.size() - 1) {
+ colors.append(',');
+ }
line(sb, MessageFormat.format("{0}.setValue({1,number,0}, 0, ''{2}'');", dName, i,
value.name));
line(sb, MessageFormat.format("{0}.setValue({1,number,0}, 1, {2,number,0.0});", dName,
i, value.value));
}
+ colors.append(']');
// instantiate chart
String cName = "chart_" + dataName;
@@ -58,8 +68,8 @@ public class GooglePieChart extends GoogleChart {
cName, tagId));
line(sb,
MessageFormat
- .format("{0}.draw({1}, '{'width: {2,number,0}, height: {3,number,0}, chartArea:'{'left:20,top:20'}', title: ''{4}'' '}');",
- cName, dName, width, height, title));
+ .format("{0}.draw({1}, '{'width: {2,number,0}, height: {3,number,0}, chartArea:'{'left:20,top:20'}', title: ''{4}'', {5} '}');",
+ cName, dName, width, height, title, colors.toString()));
line(sb, "");
}
} \ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/ActivityPage.html b/src/com/gitblit/wicket/pages/ActivityPage.html
index c86028f2..dff5db27 100644
--- a/src/com/gitblit/wicket/pages/ActivityPage.html
+++ b/src/com/gitblit/wicket/pages/ActivityPage.html
@@ -8,7 +8,7 @@
<div class="page-header">
<h2><wicket:message key="gb.recentActivity"></wicket:message><small> / <span wicket:id="subheader">[days back]</span></small></h2>
</div>
- <div style="text-align: center;">
+ <div style="height: 155px;text-align: center;">
<span id="chartDaily"></span>
<span id="chartRepositories"></span>
<span id="chartAuthors"></span>
diff --git a/src/com/gitblit/wicket/pages/ActivityPage.java b/src/com/gitblit/wicket/pages/ActivityPage.java
index 53c7f41c..011eef14 100644
--- a/src/com/gitblit/wicket/pages/ActivityPage.java
+++ b/src/com/gitblit/wicket/pages/ActivityPage.java
@@ -15,35 +15,27 @@
*/
package com.gitblit.wicket.pages;
-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.Date;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import org.apache.wicket.PageParameters;
import org.apache.wicket.behavior.HeaderContributor;
import org.apache.wicket.markup.html.basic.Label;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
import com.gitblit.GitBlit;
-import com.gitblit.models.DailyActivity;
+import com.gitblit.models.Activity;
import com.gitblit.models.Metric;
-import com.gitblit.models.RefModel;
-import com.gitblit.models.RepositoryCommit;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
-import com.gitblit.utils.JGitUtils;
+import com.gitblit.utils.ActivityUtils;
import com.gitblit.utils.StringUtils;
-import com.gitblit.utils.TimeUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.charting.GoogleChart;
@@ -64,16 +56,50 @@ public class ActivityPage extends RootPage {
public ActivityPage(PageParameters params) {
super();
setupPage("", "");
- final UserModel user = GitBlitWebSession.get().getUser();
// parameters
int daysBack = WicketUtils.getDaysBack(params);
if (daysBack < 1) {
daysBack = 14;
- }
+ }
+ String objectId = WicketUtils.getObject(params);
+
+ // determine repositories to view and retrieve the activity
+ List<RepositoryModel> models = getRepositories(params);
+ List<Activity> recentActivity = ActivityUtils.getRecentActivity(models, daysBack, objectId);
+
+ 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"));
+ } else {
+ // calculate total commits and total authors
+ int totalCommits = 0;
+ Set<String> uniqueAuthors = new HashSet<String>();
+ for (Activity activity : recentActivity) {
+ totalCommits += activity.commits.size();
+ 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));
+ }
+ }
+
+ private List<RepositoryModel> getRepositories(PageParameters params) {
+ final UserModel user = GitBlitWebSession.get().getUser();
String set = WicketUtils.getSet(params);
String repositoryName = WicketUtils.getRepositoryName(params);
- String objectId = WicketUtils.getObject(params);
List<RepositoryModel> models = null;
if (!StringUtils.isEmpty(repositoryName)) {
@@ -103,110 +129,41 @@ public class ActivityPage extends RootPage {
}
models = setModels;
}
+ return models;
+ }
- // Activity panel shows last daysBack of activity across all
- // repositories.
- Date thresholdDate = new Date(System.currentTimeMillis() - daysBack * TimeUtils.ONEDAY);
-
- // Build a map of DailyActivity from the available repositories for the
- // specified threshold date.
- DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
- Calendar cal = Calendar.getInstance();
-
- Map<String, DailyActivity> activity = new HashMap<String, DailyActivity>();
- for (RepositoryModel model : models) {
- if (model.hasCommits && model.lastChange.after(thresholdDate)) {
- Repository repository = GitBlit.self().getRepository(model.name);
- List<RevCommit> commits = JGitUtils.getRevLog(repository, objectId, thresholdDate);
- Map<ObjectId, List<RefModel>> allRefs = JGitUtils.getAllRefs(repository);
- repository.close();
-
- // determine commit branch
- String branch = objectId;
- if (StringUtils.isEmpty(branch)) {
- List<RefModel> headRefs = allRefs.get(commits.get(0).getId());
- List<String> localBranches = new ArrayList<String>();
- for (RefModel ref : headRefs) {
- if (ref.getName().startsWith(Constants.R_HEADS)) {
- localBranches.add(ref.getName().substring(Constants.R_HEADS.length()));
- }
- }
- // determine branch
- if (localBranches.size() == 1) {
- // only one branch, choose it
- branch = localBranches.get(0);
- } else if (localBranches.size() > 1) {
- if (localBranches.contains("master")) {
- // choose master
- branch = "master";
- } else {
- // choose first branch
- branch = localBranches.get(0);
- }
- }
- }
-
- for (RevCommit commit : commits) {
- Date date = JGitUtils.getCommitDate(commit);
- String dateStr = df.format(date);
- if (!activity.containsKey(dateStr)) {
- // Normalize the date to midnight
- cal.setTime(date);
- cal.set(Calendar.HOUR_OF_DAY, 0);
- cal.set(Calendar.MINUTE, 0);
- cal.set(Calendar.SECOND, 0);
- cal.set(Calendar.MILLISECOND, 0);
- activity.put(dateStr, new DailyActivity(cal.getTime()));
- }
- RepositoryCommit commitModel = new RepositoryCommit(model.name, branch, commit);
- commitModel.setRefs(allRefs.get(commit.getId()));
- activity.get(dateStr).commits.add(commitModel);
- }
- }
- }
-
+ /**
+ * 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> dayMetrics = new HashMap<String, Metric>();
Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>();
Map<String, Metric> authorMetrics = new HashMap<String, Metric>();
- // prepare day metrics
- cal.setTimeInMillis(System.currentTimeMillis());
- for (int i = 0; i < daysBack; i++) {
- cal.add(Calendar.DATE, -1);
- String key = df.format(cal.getTime());
- dayMetrics.put(key, new Metric(key));
- }
-
- // calculate activity metrics
- for (Map.Entry<String, DailyActivity> entry : activity.entrySet()) {
- // day metrics
- Metric day = dayMetrics.get(entry.getKey());
- day.count = entry.getValue().commits.size();
+ // aggregate repository and author metrics
+ for (Activity activity : recentActivity) {
- for (RepositoryCommit commit : entry.getValue().commits) {
- // repository metrics
- String repository = commit.repository;
- if (!repositoryMetrics.containsKey(repository)) {
- repositoryMetrics.put(repository, new Metric(repository));
- }
- repositoryMetrics.get(repository).count++;
-
- // author metrics
- String author = commit.getAuthorIdent().getEmailAddress().toLowerCase();
+ // 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++;
+ authorMetrics.get(author).count += entry.getValue().count;
}
- }
- // sort the activity groups and their commit contents
- int totalCommits = 0;
- List<DailyActivity> recentActivity = new ArrayList<DailyActivity>(activity.values());
- for (DailyActivity daily : recentActivity) {
- Collections.sort(daily.commits);
- totalCommits += daily.commits.size();
+ // aggregate repository metrics
+ for (Map.Entry<String, Metric> entry : activity.getRepositoryMetrics().entrySet()) {
+ String repository = entry.getKey();
+ if (!repositoryMetrics.containsKey(repository)) {
+ repositoryMetrics.put(repository, new Metric(repository));
+ }
+ repositoryMetrics.get(repository).count += entry.getValue().count;
+ }
}
// build google charts
@@ -221,9 +178,9 @@ public class ActivityPage extends RootPage {
// daily line chart
GoogleChart chart = new GoogleLineChart("chartDaily", getString("gb.dailyActivity"), "day",
getString("gb.commits"));
- df = new SimpleDateFormat("MMM dd");
- for (DailyActivity metric : recentActivity) {
- chart.addValue(df.format(metric.date), metric.commits.size());
+ SimpleDateFormat df = new SimpleDateFormat("MMM dd");
+ for (Activity metric : recentActivity) {
+ chart.addValue(df.format(metric.startDate), metric.commits.size());
}
chart.setWidth(w);
chart.setHeight(h);
@@ -249,12 +206,6 @@ public class ActivityPage extends RootPage {
chart.setHeight(h);
charts.addChart(chart);
- add(new HeaderContributor(charts));
-
- add(new Label("subheader", MessageFormat.format(getString("gb.recentActivitySubheader"),
- daysBack, totalCommits, authorMetrics.size())));
-
- // add activity panel
- add(new ActivityPanel("activityPanel", recentActivity));
+ return charts;
}
}
diff --git a/src/com/gitblit/wicket/panels/ActivityPanel.html b/src/com/gitblit/wicket/panels/ActivityPanel.html
index 703dc009..668e7c90 100644
--- a/src/com/gitblit/wicket/panels/ActivityPanel.html
+++ b/src/com/gitblit/wicket/panels/ActivityPanel.html
@@ -16,6 +16,9 @@
<wicket:fragment wicket:id="commitFragment">
<td class="date" style="width:40px; vertical-align: middle;" ><span wicket:id="time">[time of day]</span></td>
+ <td style="width:10em;text-align:left;vertical-align: middle;">
+ <span wicket:id="repository" class="repositorySwatch">[repository link]</span>
+ </td>
<td style="width:30px;vertical-align: middle;"><img wicket:id="avatar" style="vertical-align: middle;"></img></td>
<td class="author" style="vertical-align: middle;">
<img wicket:id="commitIcon" style="vertical-align: middle;"></img>
@@ -24,7 +27,6 @@
</td>
<td style="text-align:right;vertical-align: middle;">
<div wicket:id="commitRefs">[commit refs]</div>
- <span wicket:id="repository">[repository link]</span>
</td>
<td class="rightAlign" style="width:7em;vertical-align: middle;">
<span class="link">
diff --git a/src/com/gitblit/wicket/panels/ActivityPanel.java b/src/com/gitblit/wicket/panels/ActivityPanel.java
index 128ef2bd..e9ec0741 100644
--- a/src/com/gitblit/wicket/panels/ActivityPanel.java
+++ b/src/com/gitblit/wicket/panels/ActivityPanel.java
@@ -25,8 +25,9 @@ import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import com.gitblit.Constants;
-import com.gitblit.models.DailyActivity;
-import com.gitblit.models.RepositoryCommit;
+import com.gitblit.models.Activity;
+import com.gitblit.models.Activity.RepositoryCommit;
+import com.gitblit.utils.StringUtils;
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.GravatarImage;
import com.gitblit.wicket.WicketUtils;
@@ -47,18 +48,18 @@ public class ActivityPanel extends BasePanel {
private static final long serialVersionUID = 1L;
- public ActivityPanel(String wicketId, List<DailyActivity> recentActivity) {
+ public ActivityPanel(String wicketId, List<Activity> recentActivity) {
super(wicketId);
Collections.sort(recentActivity);
- DataView<DailyActivity> activityView = new DataView<DailyActivity>("activity",
- new ListDataProvider<DailyActivity>(recentActivity)) {
+ DataView<Activity> activityView = new DataView<Activity>("activity",
+ new ListDataProvider<Activity>(recentActivity)) {
private static final long serialVersionUID = 1L;
- public void populateItem(final Item<DailyActivity> item) {
- final DailyActivity entry = item.getModelObject();
- item.add(WicketUtils.createDatestampLabel("title", entry.date, GitBlitWebSession
+ public void populateItem(final Item<Activity> item) {
+ final Activity entry = item.getModelObject();
+ item.add(WicketUtils.createDatestampLabel("title", entry.startDate, GitBlitWebSession
.get().getTimezone()));
// display the commits in chronological order
@@ -93,10 +94,11 @@ public class ActivityPanel extends BasePanel {
setPersonSearchTooltip(authorLink, author, Constants.SearchType.AUTHOR);
fragment.add(authorLink);
- // repository summary page link
- LinkPanel repositoryLink = new LinkPanel("repository", "list",
+ // repository
+ LinkPanel repositoryLink = new LinkPanel("repository", null,
commit.repository, SummaryPage.class,
WicketUtils.newRepositoryParameter(commit.repository));
+ WicketUtils.setCssBackground(repositoryLink, commit.repository);
fragment.add(repositoryLink);
// repository branch
@@ -113,9 +115,13 @@ public class ActivityPanel extends BasePanel {
// message/commit link
String shortMessage = commit.getShortMessage();
- LinkPanel shortlog = new LinkPanel("message", "list subject", shortMessage,
- CommitPage.class, WicketUtils.newObjectParameter(commit.repository,
- commit.getName()));
+ String trimmedMessage = StringUtils.trimShortLog(shortMessage);
+ LinkPanel shortlog = new LinkPanel("message", "list subject",
+ trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter(
+ commit.repository, commit.getName()));
+ if (!shortMessage.equals(trimmedMessage)) {
+ WicketUtils.setHtmlTooltip(shortlog, shortMessage);
+ }
fragment.add(shortlog);
// refs