From db91a34ccb5135f733c7431fdba49669131e97da Mon Sep 17 00:00:00 2001 From: James Moger Date: Sat, 19 Nov 2011 07:33:59 -0500 Subject: [PATCH] Reorganizing the recent activity feature --- src/com/gitblit/models/Activity.java | 169 ++++++++++++++++ src/com/gitblit/models/DailyActivity.java | 47 ----- src/com/gitblit/models/RepositoryCommit.java | 86 -------- src/com/gitblit/utils/ActivityUtils.java | 130 ++++++++++++ .../gitblit/wicket/GitBlitWebApp.properties | 3 +- src/com/gitblit/wicket/WicketUtils.java | 23 ++- .../gitblit/wicket/charting/GoogleCharts.java | 4 +- .../wicket/charting/GooglePieChart.java | 14 +- .../gitblit/wicket/pages/ActivityPage.html | 2 +- .../gitblit/wicket/pages/ActivityPage.java | 187 +++++++----------- .../gitblit/wicket/panels/ActivityPanel.html | 4 +- .../gitblit/wicket/panels/ActivityPanel.java | 32 +-- 12 files changed, 422 insertions(+), 279 deletions(-) create mode 100644 src/com/gitblit/models/Activity.java delete mode 100644 src/com/gitblit/models/DailyActivity.java delete mode 100644 src/com/gitblit/models/RepositoryCommit.java create mode 100644 src/com/gitblit/utils/ActivityUtils.java 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 { + + private static final long serialVersionUID = 1L; + + public final Date startDate; + + public final Date endDate; + + public final List commits; + + private final Map authorMetrics; + + private final Map 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(); + authorMetrics = new HashMap(); + repositoryMetrics = new HashMap(); + } + + 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 getAuthorMetrics() { + return authorMetrics; + } + + public Map 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 { + + private static final long serialVersionUID = 1L; + + public final String repository; + + public final String branch; + + private final RevCommit commit; + + private List refs; + + public RepositoryCommit(String repository, String branch, RevCommit commit) { + this.repository = repository; + this.branch = branch; + this.commit = commit; + } + + public void setRefs(List refs) { + this.refs = refs; + } + + public List 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 { - - private static final long serialVersionUID = 1L; - - public final Date date; - - public final List commits; - - public DailyActivity(Date date) { - this.date = date; - commits = new ArrayList(); - } - - @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 { - - private static final long serialVersionUID = 1L; - - public final String repository; - - public final String branch; - - private final RevCommit commit; - - private List refs; - - public RepositoryCommit(String repository, String branch, RevCommit commit) { - this.repository = repository; - this.branch = branch; - this.commit = commit; - } - - public void setRefs(List refs) { - this.refs = refs; - } - - public List 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 getRecentActivity(List 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 activity = new HashMap(); + for (RepositoryModel model : models) { + if (model.hasCommits && model.lastChange.after(thresholdDate)) { + Repository repository = GitBlit.self().getRepository(model.name); + List commits = JGitUtils.getRevLog(repository, objectId, thresholdDate); + Map> allRefs = JGitUtils.getAllRefs(repository); + repository.close(); + + // determine commit branch + String branch = objectId; + if (StringUtils.isEmpty(branch)) { + List headRefs = allRefs.get(commits.get(0).getId()); + List localBranches = new ArrayList(); + 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 recentActivity = new ArrayList(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 charts = new ArrayList(); + public final List charts = new ArrayList(); 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 @@ -
+
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 models = getRepositories(params); + List 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 uniqueAuthors = new HashSet(); + 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 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 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 activity = new HashMap(); - for (RepositoryModel model : models) { - if (model.hasCommits && model.lastChange.after(thresholdDate)) { - Repository repository = GitBlit.self().getRepository(model.name); - List commits = JGitUtils.getRevLog(repository, objectId, thresholdDate); - Map> allRefs = JGitUtils.getAllRefs(repository); - repository.close(); - - // determine commit branch - String branch = objectId; - if (StringUtils.isEmpty(branch)) { - List headRefs = allRefs.get(commits.get(0).getId()); - List localBranches = new ArrayList(); - 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 recentActivity) { // activity metrics - Map dayMetrics = new HashMap(); Map repositoryMetrics = new HashMap(); Map authorMetrics = new HashMap(); - // 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 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 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 recentActivity = new ArrayList(activity.values()); - for (DailyActivity daily : recentActivity) { - Collections.sort(daily.commits); - totalCommits += daily.commits.size(); + // aggregate repository metrics + for (Map.Entry 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 @@ [time of day] + + [repository link] + @@ -24,7 +27,6 @@
[commit refs]
- [repository 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 recentActivity) { + public ActivityPanel(String wicketId, List recentActivity) { super(wicketId); Collections.sort(recentActivity); - DataView activityView = new DataView("activity", - new ListDataProvider(recentActivity)) { + DataView activityView = new DataView("activity", + new ListDataProvider(recentActivity)) { private static final long serialVersionUID = 1L; - public void populateItem(final Item item) { - final DailyActivity entry = item.getModelObject(); - item.add(WicketUtils.createDatestampLabel("title", entry.date, GitBlitWebSession + public void populateItem(final Item 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 -- 2.39.5