@@ -161,12 +161,23 @@ web.repositoriesMessage = gitblit | |||
# RESTART REQUIRED | |||
web.useClientTimezone = false | |||
# Time format | |||
# <http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html> | |||
# | |||
# SINCE 0.8.0 | |||
web.timeFormat = HH:mm | |||
# Short date format | |||
# <http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html> | |||
# | |||
# SINCE 0.5.0 | |||
web.datestampShortFormat = yyyy-MM-dd | |||
# Long date format | |||
# | |||
# SINCE 0.8.0 | |||
web.datestampLongFormat = EEEE, MMMM d, yyyy | |||
# Long timestamp format | |||
# <http://download.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html> | |||
# | |||
@@ -239,6 +250,12 @@ web.showSearchTypeSelection = false | |||
# SINCE 0.5.0 | |||
web.generateActivityGraph = true | |||
# The number of days to show on the activity page. | |||
# Value must exceed 0 else default of 14 is used | |||
# | |||
# SINCE 0.8.0 | |||
web.activityDuration = 14 | |||
# The number of commits to display on the summary page | |||
# Value must exceed 0 else default of 20 is used | |||
# |
@@ -5,6 +5,11 @@ | |||
- added: optional Gravatar integration | |||
**New:** *web.allowGravatar = true* | |||
- added: multi-repository activity page. this is a timeline of commit activity over the last N days for one or more repositories. | |||
**New:** *web.activityDuration = 14* | |||
**New:** *web.timeFormat = HH:mm* | |||
**New:** *web.datestampLongFormat = EEEE, MMMM d, yyyy* | |||
### Older Releases | |||
@@ -0,0 +1,47 @@ | |||
/* | |||
* 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); | |||
} | |||
} |
@@ -0,0 +1,86 @@ | |||
/* | |||
* 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; | |||
} | |||
} |
@@ -25,6 +25,7 @@ import org.apache.wicket.protocol.http.WebApplication; | |||
import com.gitblit.GitBlit; | |||
import com.gitblit.Keys; | |||
import com.gitblit.wicket.pages.ActivityPage; | |||
import com.gitblit.wicket.pages.BlamePage; | |||
import com.gitblit.wicket.pages.BlobDiffPage; | |||
import com.gitblit.wicket.pages.BlobPage; | |||
@@ -103,6 +104,8 @@ public class GitBlitWebApp extends WebApplication { | |||
// federation urls | |||
mount("/proposal", ReviewProposalPage.class, "t"); | |||
mount("/registration", FederationRegistrationPage.class, "u", "n"); | |||
mount("/activity", ActivityPage.class, "r", "h"); | |||
} | |||
private void mount(String location, Class<? extends WebPage> clazz, String... parameters) { |
@@ -180,4 +180,10 @@ gb.date = date | |||
gb.activity = activity | |||
gb.subscribe = subscribe | |||
gb.branch = branch | |||
gb.maxHits = max hits | |||
gb.maxHits = max hits | |||
gb.recentActivity = recent activity | |||
gb.recentActivitySubheader = last {0} days / {1} commits by {2} authors | |||
gb.dailyActivity = daily activity | |||
gb.activeRepositories = active repositories | |||
gb.activeAuthors = active authors | |||
gb.commits = commits |
@@ -358,6 +358,14 @@ public class WicketUtils { | |||
return params.getInt("pg", 1); | |||
} | |||
public static String getSet(PageParameters params) { | |||
return params.getString("set", ""); | |||
} | |||
public static int getDaysBack(PageParameters params) { | |||
return params.getInt("db", 14); | |||
} | |||
public static String getUsername(PageParameters params) { | |||
return params.getString("user", ""); | |||
} | |||
@@ -403,6 +411,57 @@ 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); | |||
if (timeZone != null) { | |||
df.setTimeZone(timeZone); | |||
} | |||
String timeString; | |||
if (date.getTime() == 0) { | |||
timeString = "--"; | |||
} else { | |||
timeString = df.format(date); | |||
} | |||
String title = TimeUtils.timeAgo(date); | |||
Label label = new Label(wicketId, timeString); | |||
WicketUtils.setCssClass(label, TimeUtils.timeAgoCss(date)); | |||
if (!StringUtils.isEmpty(title)) { | |||
WicketUtils.setHtmlTooltip(label, title); | |||
} | |||
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); | |||
if (timeZone != null) { | |||
df.setTimeZone(timeZone); | |||
} | |||
String dateString; | |||
if (date.getTime() == 0) { | |||
dateString = "--"; | |||
} else { | |||
dateString = df.format(date); | |||
} | |||
String title = null; | |||
if (date.getTime() <= System.currentTimeMillis()) { | |||
// past | |||
title = TimeUtils.timeAgo(date); | |||
} | |||
if ((System.currentTimeMillis() - date.getTime()) < 10 * 24 * 60 * 60 * 1000L) { | |||
String tmp = dateString; | |||
dateString = title; | |||
title = tmp; | |||
} | |||
Label label = new Label(wicketId, dateString); | |||
WicketUtils.setCssClass(label, TimeUtils.timeAgoCss(date)); | |||
if (!StringUtils.isEmpty(title)) { | |||
WicketUtils.setHtmlTooltip(label, title); | |||
} | |||
return label; | |||
} | |||
public static Label createTimestampLabel(String wicketId, Date date, TimeZone timeZone) { | |||
String format = GitBlit.getString(Keys.web.datetimestampLongFormat, |
@@ -0,0 +1,19 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" | |||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||
xml:lang="en" | |||
lang="en"> | |||
<body> | |||
<wicket:extend> | |||
<div class="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;"> | |||
<span id="chartDaily"></span> | |||
<span id="chartRepositories"></span> | |||
<span id="chartAuthors"></span> | |||
</div> | |||
<div wicket:id="activityPanel" style="padding-top:5px;" >[activity panel]</div> | |||
</wicket:extend> | |||
</body> | |||
</html> |
@@ -0,0 +1,260 @@ | |||
/* | |||
* 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.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.List; | |||
import java.util.Map; | |||
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.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.StringUtils; | |||
import com.gitblit.utils.TimeUtils; | |||
import com.gitblit.wicket.GitBlitWebSession; | |||
import com.gitblit.wicket.WicketUtils; | |||
import com.gitblit.wicket.charting.GoogleChart; | |||
import com.gitblit.wicket.charting.GoogleCharts; | |||
import com.gitblit.wicket.charting.GoogleLineChart; | |||
import com.gitblit.wicket.charting.GooglePieChart; | |||
import com.gitblit.wicket.panels.ActivityPanel; | |||
/** | |||
* Activity Page shows a list of recent commits across all visible Gitblit | |||
* repositories. | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
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 set = WicketUtils.getSet(params); | |||
String repositoryName = WicketUtils.getRepositoryName(params); | |||
String objectId = WicketUtils.getObject(params); | |||
List<RepositoryModel> models = null; | |||
if (!StringUtils.isEmpty(repositoryName)) { | |||
// named repository | |||
models = new ArrayList<RepositoryModel>(); | |||
RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName); | |||
if (user.canAccessRepository(model)) { | |||
models.add(model); | |||
} | |||
} | |||
// get all user accessible repositories | |||
if (models == null) { | |||
models = GitBlit.self().getRepositoryModels(user); | |||
} | |||
// filter the repositories by the specified set | |||
if (!StringUtils.isEmpty(set)) { | |||
List<String> sets = StringUtils.getStringsFromValue(set, ","); | |||
List<RepositoryModel> setModels = new ArrayList<RepositoryModel>(); | |||
for (RepositoryModel model : models) { | |||
for (String curr : sets) { | |||
if (model.federationSets.contains(curr)) { | |||
setModels.add(model); | |||
} | |||
} | |||
} | |||
models = setModels; | |||
} | |||
// 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); | |||
} | |||
} | |||
} | |||
// 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(); | |||
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(); | |||
if (!authorMetrics.containsKey(author)) { | |||
authorMetrics.put(author, new Metric(author)); | |||
} | |||
authorMetrics.get(author).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(); | |||
} | |||
// build google charts | |||
int w = 310; | |||
int h = 150; | |||
GoogleCharts charts = new GoogleCharts(); | |||
// sort in reverse-chronological order and then reverse that | |||
Collections.sort(recentActivity); | |||
Collections.reverse(recentActivity); | |||
// daily line chart | |||
GoogleChart chart = new GoogleLineChart("chartDaily", getString("gb.dailyActivity"), "day", | |||
getString("gb.commits")); | |||
df = new SimpleDateFormat("MMM dd"); | |||
for (DailyActivity metric : recentActivity) { | |||
chart.addValue(df.format(metric.date), metric.commits.size()); | |||
} | |||
chart.setWidth(w); | |||
chart.setHeight(h); | |||
charts.addChart(chart); | |||
// active repositories pie chart | |||
chart = new GooglePieChart("chartRepositories", getString("gb.activeRepositories"), | |||
getString("gb.repository"), getString("gb.commits")); | |||
for (Metric metric : repositoryMetrics.values()) { | |||
chart.addValue(metric.name, metric.count); | |||
} | |||
chart.setWidth(w); | |||
chart.setHeight(h); | |||
charts.addChart(chart); | |||
// active authors pie chart | |||
chart = new GooglePieChart("chartAuthors", getString("gb.activeAuthors"), | |||
getString("gb.author"), getString("gb.commits")); | |||
for (Metric metric : authorMetrics.values()) { | |||
chart.addValue(metric.name, metric.count); | |||
} | |||
chart.setWidth(w); | |||
chart.setHeight(h); | |||
charts.addChart(chart); | |||
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)); | |||
} | |||
} |
@@ -82,6 +82,7 @@ public abstract class RootPage extends BasePage { | |||
// navigation links | |||
List<PageRegistration> pages = new ArrayList<PageRegistration>(); | |||
pages.add(new PageRegistration("gb.repositories", RepositoriesPage.class)); | |||
pages.add(new PageRegistration("gb.activity", ActivityPage.class)); | |||
if (showAdmin) { | |||
pages.add(new PageRegistration("gb.users", UsersPage.class)); | |||
} |
@@ -0,0 +1,38 @@ | |||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |||
<html xmlns="http://www.w3.org/1999/xhtml" | |||
xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.3-strict.dtd" | |||
xml:lang="en" | |||
lang="en"> | |||
<body> | |||
<wicket:panel> | |||
<div wicket:id="activity"> | |||
<div class="header"><span wicket:id="title">[title]</span></div> | |||
<table wicket:id="commits"> | |||
<tr wicket:id="commit"></tr> | |||
</table> | |||
</div> | |||
<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: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> | |||
<span wicket:id="message">[shortlog commit link]</span><br/> | |||
<span wicket:id="author" style="padding-left:20px;">[author link]</span> committed <span wicket:id="commitid">[commit id]</span> to <span wicket:id="branch"></span> | |||
</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"> | |||
<a wicket:id="view"><wicket:message key="gb.view"></wicket:message></a> | <a wicket:id="diff"><wicket:message key="gb.diff"></wicket:message></a> | <a wicket:id="tree"><wicket:message key="gb.tree"></wicket:message></a> | |||
</span> | |||
</td> | |||
</wicket:fragment> | |||
</wicket:panel> | |||
</body> | |||
</html> |
@@ -0,0 +1,142 @@ | |||
/* | |||
* 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.wicket.panels; | |||
import java.util.Collections; | |||
import java.util.List; | |||
import org.apache.wicket.markup.html.link.BookmarkablePageLink; | |||
import org.apache.wicket.markup.html.panel.Fragment; | |||
import org.apache.wicket.markup.repeater.Item; | |||
import org.apache.wicket.markup.repeater.data.DataView; | |||
import org.apache.wicket.markup.repeater.data.ListDataProvider; | |||
import com.gitblit.Constants; | |||
import com.gitblit.models.DailyActivity; | |||
import com.gitblit.models.RepositoryCommit; | |||
import com.gitblit.wicket.GitBlitWebSession; | |||
import com.gitblit.wicket.GravatarImage; | |||
import com.gitblit.wicket.WicketUtils; | |||
import com.gitblit.wicket.pages.CommitDiffPage; | |||
import com.gitblit.wicket.pages.CommitPage; | |||
import com.gitblit.wicket.pages.LogPage; | |||
import com.gitblit.wicket.pages.SearchPage; | |||
import com.gitblit.wicket.pages.SummaryPage; | |||
import com.gitblit.wicket.pages.TreePage; | |||
/** | |||
* Renders activity in day-blocks in reverse-chronological order. | |||
* | |||
* @author James Moger | |||
* | |||
*/ | |||
public class ActivityPanel extends BasePanel { | |||
private static final long serialVersionUID = 1L; | |||
public ActivityPanel(String wicketId, List<DailyActivity> recentActivity) { | |||
super(wicketId); | |||
Collections.sort(recentActivity); | |||
DataView<DailyActivity> activityView = new DataView<DailyActivity>("activity", | |||
new ListDataProvider<DailyActivity>(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 | |||
.get().getTimezone())); | |||
// display the commits in chronological order | |||
DataView<RepositoryCommit> commits = new DataView<RepositoryCommit>("commits", | |||
new ListDataProvider<RepositoryCommit>(entry.commits)) { | |||
private static final long serialVersionUID = 1L; | |||
public void populateItem(final Item<RepositoryCommit> item) { | |||
final RepositoryCommit commit = item.getModelObject(); | |||
Fragment fragment = new Fragment("commit", "commitFragment", this); | |||
// time of day | |||
fragment.add(WicketUtils.createTimeLabel("time", commit.getAuthorIdent() | |||
.getWhen(), GitBlitWebSession.get().getTimezone())); | |||
// avatar | |||
fragment.add(new GravatarImage("avatar", commit.getAuthorIdent(), 36)); | |||
// merge icon | |||
if (commit.getParentCount() > 1) { | |||
fragment.add(WicketUtils.newImage("commitIcon", | |||
"commit_merge_16x16.png")); | |||
} else { | |||
fragment.add(WicketUtils.newBlankImage("commitIcon")); | |||
} | |||
// author search link | |||
String author = commit.getAuthorIdent().getName(); | |||
LinkPanel authorLink = new LinkPanel("author", "list", author, | |||
SearchPage.class, WicketUtils.newSearchParameter(commit.repository, | |||
commit.getName(), author, Constants.SearchType.AUTHOR)); | |||
setPersonSearchTooltip(authorLink, author, Constants.SearchType.AUTHOR); | |||
fragment.add(authorLink); | |||
// repository summary page link | |||
LinkPanel repositoryLink = new LinkPanel("repository", "list", | |||
commit.repository, SummaryPage.class, | |||
WicketUtils.newRepositoryParameter(commit.repository)); | |||
fragment.add(repositoryLink); | |||
// repository branch | |||
LinkPanel branchLink = new LinkPanel("branch", "list", commit.branch, | |||
LogPage.class, WicketUtils.newObjectParameter(commit.repository, | |||
commit.branch)); | |||
WicketUtils.setCssStyle(branchLink, "color: #008000;"); | |||
fragment.add(branchLink); | |||
LinkPanel commitid = new LinkPanel("commitid", "list subject", | |||
commit.getShortName(), CommitPage.class, | |||
WicketUtils.newObjectParameter(commit.repository, commit.getName())); | |||
fragment.add(commitid); | |||
// message/commit link | |||
String shortMessage = commit.getShortMessage(); | |||
LinkPanel shortlog = new LinkPanel("message", "list subject", shortMessage, | |||
CommitPage.class, WicketUtils.newObjectParameter(commit.repository, | |||
commit.getName())); | |||
fragment.add(shortlog); | |||
// refs | |||
fragment.add(new RefsPanel("commitRefs", commit.repository, commit | |||
.getRefs())); | |||
// view, diff, tree links | |||
fragment.add(new BookmarkablePageLink<Void>("view", CommitPage.class, | |||
WicketUtils.newObjectParameter(commit.repository, commit.getName()))); | |||
fragment.add(new BookmarkablePageLink<Void>("diff", CommitDiffPage.class, | |||
WicketUtils.newObjectParameter(commit.repository, commit.getName())) | |||
.setEnabled(commit.getParentCount() > 0)); | |||
fragment.add(new BookmarkablePageLink<Void>("tree", TreePage.class, | |||
WicketUtils.newObjectParameter(commit.repository, commit.getName()))); | |||
item.add(fragment); | |||
} | |||
}; | |||
item.add(commits); | |||
} | |||
}; | |||
add(activityView); | |||
} | |||
} |