You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

DashboardPage.java 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright 2013 gitblit.com.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package com.gitblit.wicket.pages;
  17. import java.text.MessageFormat;
  18. import java.util.ArrayList;
  19. import java.util.Calendar;
  20. import java.util.Collection;
  21. import java.util.Collections;
  22. import java.util.Date;
  23. import java.util.HashMap;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Set;
  27. import java.util.TimeZone;
  28. import java.util.TreeSet;
  29. import org.apache.wicket.PageParameters;
  30. import org.apache.wicket.behavior.HeaderContributor;
  31. import org.apache.wicket.markup.html.basic.Label;
  32. import org.apache.wicket.markup.html.panel.Fragment;
  33. import org.eclipse.jgit.lib.Repository;
  34. import com.gitblit.Keys;
  35. import com.gitblit.models.DailyLogEntry;
  36. import com.gitblit.models.Menu.ParameterMenuItem;
  37. import com.gitblit.models.NavLink.DropDownPageMenuNavLink;
  38. import com.gitblit.models.Metric;
  39. import com.gitblit.models.NavLink;
  40. import com.gitblit.models.RefLogEntry;
  41. import com.gitblit.models.RepositoryCommit;
  42. import com.gitblit.models.RepositoryModel;
  43. import com.gitblit.models.UserModel;
  44. import com.gitblit.utils.ArrayUtils;
  45. import com.gitblit.utils.RefLogUtils;
  46. import com.gitblit.utils.StringUtils;
  47. import com.gitblit.wicket.GitBlitWebApp;
  48. import com.gitblit.wicket.charting.Chart;
  49. import com.gitblit.wicket.charting.Charts;
  50. import com.gitblit.wicket.charting.Flotr2Charts;
  51. import com.gitblit.wicket.panels.DigestsPanel;
  52. import com.gitblit.wicket.panels.LinkPanel;
  53. public abstract class DashboardPage extends RootPage {
  54. public DashboardPage() {
  55. super();
  56. }
  57. public DashboardPage(PageParameters params) {
  58. super(params);
  59. }
  60. @Override
  61. protected boolean reusePageParameters() {
  62. return true;
  63. }
  64. protected void addActivity(UserModel user, Collection<RepositoryModel> repositories, String feedTitle, int daysBack) {
  65. Calendar c = Calendar.getInstance();
  66. c.add(Calendar.DATE, -1*daysBack);
  67. Date minimumDate = c.getTime();
  68. TimeZone timezone = getTimeZone();
  69. // create daily commit digest feed
  70. List<DailyLogEntry> digests = new ArrayList<DailyLogEntry>();
  71. for (RepositoryModel model : repositories) {
  72. if (model.isCollectingGarbage) {
  73. continue;
  74. }
  75. if (model.hasCommits && model.lastChange.after(minimumDate)) {
  76. Repository repository = app().repositories().getRepository(model.name);
  77. List<DailyLogEntry> entries = RefLogUtils.getDailyLogByRef(model.name, repository, minimumDate, timezone);
  78. digests.addAll(entries);
  79. repository.close();
  80. }
  81. }
  82. Fragment activityFragment = new Fragment("activity", "activityFragment", this);
  83. add(activityFragment);
  84. activityFragment.add(new Label("feedTitle", feedTitle));
  85. if (digests.size() == 0) {
  86. // quiet or no starred repositories
  87. if (repositories.size() == 0) {
  88. if (UserModel.ANONYMOUS.equals(user)) {
  89. if (daysBack == 1) {
  90. activityFragment.add(new Label("digests", getString("gb.noActivityToday")));
  91. } else {
  92. activityFragment.add(new Label("digests", MessageFormat.format(getString("gb.noActivity"), daysBack)));
  93. }
  94. } else {
  95. activityFragment.add(new LinkPanel("digests", null, getString("gb.findSomeRepositories"), RepositoriesPage.class));
  96. }
  97. } else {
  98. if (daysBack == 1) {
  99. activityFragment.add(new Label("digests", getString("gb.noActivityToday")));
  100. } else {
  101. activityFragment.add(new Label("digests", MessageFormat.format(getString("gb.noActivity"), daysBack)));
  102. }
  103. }
  104. } else {
  105. // show daily commit digest feed
  106. Collections.sort(digests);
  107. DigestsPanel digestsPanel = new DigestsPanel("digests", digests);
  108. activityFragment.add(digestsPanel);
  109. }
  110. // add the nifty charts
  111. if (!ArrayUtils.isEmpty(digests)) {
  112. // aggregate author exclusions
  113. Set<String> authorExclusions = new TreeSet<String>();
  114. for (String author : app().settings().getStrings(Keys.web.metricAuthorExclusions)) {
  115. authorExclusions.add(author.toLowerCase());
  116. }
  117. for (RepositoryModel model : repositories) {
  118. if (!ArrayUtils.isEmpty(model.metricAuthorExclusions)) {
  119. for (String author : model.metricAuthorExclusions) {
  120. authorExclusions.add(author.toLowerCase());
  121. }
  122. }
  123. }
  124. addCharts(activityFragment, digests, authorExclusions, daysBack);
  125. } else {
  126. activityFragment.add(new Label("charts").setVisible(false));
  127. activityFragment.add(new Label("feedheader").setVisible(false));
  128. }
  129. }
  130. @Override
  131. protected void addDropDownMenus(List<NavLink> navLinks) {
  132. PageParameters params = getPageParameters();
  133. DropDownPageMenuNavLink menu = new DropDownPageMenuNavLink("gb.filters",
  134. GitBlitWebApp.get().getHomePage());
  135. // preserve repository filter option on time choices
  136. menu.menuItems.addAll(getTimeFilterItems(params));
  137. if (menu.menuItems.size() > 0) {
  138. // Reset Filter
  139. menu.menuItems.add(new ParameterMenuItem(getString("gb.reset")));
  140. }
  141. navLinks.add(menu);
  142. }
  143. /**
  144. * Creates the daily activity line chart, the active repositories pie chart,
  145. * and the active authors pie chart
  146. *
  147. * @param recentChanges
  148. * @param authorExclusions
  149. * @param daysBack
  150. */
  151. protected void addCharts(Fragment frag, List<DailyLogEntry> recentChanges, Set<String> authorExclusions, int daysBack) {
  152. // activity metrics
  153. Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>();
  154. Map<String, Metric> authorMetrics = new HashMap<String, Metric>();
  155. // aggregate repository and author metrics
  156. int totalCommits = 0;
  157. for (RefLogEntry change : recentChanges) {
  158. // aggregate repository metrics
  159. String repository = StringUtils.stripDotGit(change.repository);
  160. if (!repositoryMetrics.containsKey(repository)) {
  161. repositoryMetrics.put(repository, new Metric(repository));
  162. }
  163. repositoryMetrics.get(repository).count += 1;
  164. for (RepositoryCommit commit : change.getCommits()) {
  165. totalCommits++;
  166. String author = StringUtils.removeNewlines(commit.getAuthorIdent().getName());
  167. String authorName = author.toLowerCase();
  168. String authorEmail = StringUtils.removeNewlines(commit.getAuthorIdent().getEmailAddress()).toLowerCase();
  169. if (!authorExclusions.contains(authorName) && !authorExclusions.contains(authorEmail)) {
  170. if (!authorMetrics.containsKey(author)) {
  171. authorMetrics.put(author, new Metric(author));
  172. }
  173. authorMetrics.get(author).count += 1;
  174. }
  175. }
  176. }
  177. String headerPattern;
  178. if (daysBack == 1) {
  179. // today
  180. if (totalCommits == 0) {
  181. headerPattern = getString("gb.todaysActivityNone");
  182. } else {
  183. headerPattern = getString("gb.todaysActivityStats");
  184. }
  185. } else {
  186. // multiple days
  187. if (totalCommits == 0) {
  188. headerPattern = getString("gb.recentActivityNone");
  189. } else {
  190. headerPattern = getString("gb.recentActivityStats");
  191. }
  192. }
  193. frag.add(new Label("feedheader", MessageFormat.format(headerPattern,
  194. daysBack, totalCommits, authorMetrics.size())));
  195. if (app().settings().getBoolean(Keys.web.generateActivityGraph, true)) {
  196. // build google charts
  197. Charts charts = new Flotr2Charts();
  198. // active repositories pie chart
  199. Chart chart = charts.createPieChart("chartRepositories", getString("gb.activeRepositories"),
  200. getString("gb.repository"), getString("gb.commits"));
  201. for (Metric metric : repositoryMetrics.values()) {
  202. chart.addValue(metric.name, metric.count);
  203. }
  204. chart.setShowLegend(false);
  205. String url = urlFor(SummaryPage.class, null).toString() + "?r=";
  206. chart.setClickUrl(url);
  207. charts.addChart(chart);
  208. // active authors pie chart
  209. chart = charts.createPieChart("chartAuthors", getString("gb.activeAuthors"),
  210. getString("gb.author"), getString("gb.commits"));
  211. for (Metric metric : authorMetrics.values()) {
  212. chart.addValue(metric.name, metric.count);
  213. }
  214. chart.setShowLegend(false);
  215. charts.addChart(chart);
  216. add(new HeaderContributor(charts));
  217. frag.add(new Fragment("charts", "chartsFragment", this));
  218. } else {
  219. frag.add(new Label("charts").setVisible(false));
  220. }
  221. }
  222. }