]> source.dussan.org Git - gitblit.git/commitdiff
Reorganizing the recent activity feature
authorJames Moger <james.moger@gitblit.com>
Sat, 19 Nov 2011 12:33:59 +0000 (07:33 -0500)
committerJames Moger <james.moger@gitblit.com>
Sat, 19 Nov 2011 12:33:59 +0000 (07:33 -0500)
12 files changed:
src/com/gitblit/models/Activity.java [new file with mode: 0644]
src/com/gitblit/models/DailyActivity.java [deleted file]
src/com/gitblit/models/RepositoryCommit.java [deleted file]
src/com/gitblit/utils/ActivityUtils.java [new file with mode: 0644]
src/com/gitblit/wicket/GitBlitWebApp.properties
src/com/gitblit/wicket/WicketUtils.java
src/com/gitblit/wicket/charting/GoogleCharts.java
src/com/gitblit/wicket/charting/GooglePieChart.java
src/com/gitblit/wicket/pages/ActivityPage.html
src/com/gitblit/wicket/pages/ActivityPage.java
src/com/gitblit/wicket/panels/ActivityPanel.html
src/com/gitblit/wicket/panels/ActivityPanel.java

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