Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

DashboardPage.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  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.io.Serializable;
  18. import java.text.DateFormat;
  19. import java.text.MessageFormat;
  20. import java.text.SimpleDateFormat;
  21. import java.util.ArrayList;
  22. import java.util.Calendar;
  23. import java.util.Collection;
  24. import java.util.Collections;
  25. import java.util.Date;
  26. import java.util.HashMap;
  27. import java.util.List;
  28. import java.util.Map;
  29. import java.util.Set;
  30. import java.util.TimeZone;
  31. import java.util.TreeSet;
  32. import org.apache.wicket.PageParameters;
  33. import org.apache.wicket.behavior.HeaderContributor;
  34. import org.apache.wicket.markup.html.basic.Label;
  35. import org.apache.wicket.markup.html.panel.Fragment;
  36. import org.eclipse.jgit.lib.Repository;
  37. import com.gitblit.GitBlit;
  38. import com.gitblit.Keys;
  39. import com.gitblit.models.DailyLogEntry;
  40. import com.gitblit.models.Metric;
  41. import com.gitblit.models.RefLogEntry;
  42. import com.gitblit.models.RepositoryCommit;
  43. import com.gitblit.models.RepositoryModel;
  44. import com.gitblit.models.UserModel;
  45. import com.gitblit.utils.ArrayUtils;
  46. import com.gitblit.utils.RefLogUtils;
  47. import com.gitblit.utils.StringUtils;
  48. import com.gitblit.wicket.GitBlitWebApp;
  49. import com.gitblit.wicket.PageRegistration;
  50. import com.gitblit.wicket.PageRegistration.DropDownMenuItem;
  51. import com.gitblit.wicket.PageRegistration.DropDownMenuRegistration;
  52. import com.gitblit.wicket.charting.GoogleChart;
  53. import com.gitblit.wicket.charting.GoogleCharts;
  54. import com.gitblit.wicket.charting.GooglePieChart;
  55. import com.gitblit.wicket.ng.NgController;
  56. import com.gitblit.wicket.panels.DigestsPanel;
  57. import com.gitblit.wicket.panels.LinkPanel;
  58. public abstract class DashboardPage extends RootPage {
  59. public DashboardPage() {
  60. super();
  61. }
  62. public DashboardPage(PageParameters params) {
  63. super(params);
  64. }
  65. @Override
  66. protected boolean reusePageParameters() {
  67. return true;
  68. }
  69. protected void addActivity(UserModel user, Collection<RepositoryModel> repositories, String feedTitle, int daysBack) {
  70. Calendar c = Calendar.getInstance();
  71. c.add(Calendar.DATE, -1*daysBack);
  72. Date minimumDate = c.getTime();
  73. TimeZone timezone = getTimeZone();
  74. // create daily commit digest feed
  75. List<DailyLogEntry> digests = new ArrayList<DailyLogEntry>();
  76. for (RepositoryModel model : repositories) {
  77. Repository repository = GitBlit.self().getRepository(model.name);
  78. List<DailyLogEntry> entries = RefLogUtils.getDailyLogByRef(model.name, repository, minimumDate, timezone);
  79. digests.addAll(entries);
  80. repository.close();
  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 : GitBlit.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. protected Fragment createNgList(String wicketId, String fragmentId, String ngController, List<RepositoryModel> repositories) {
  131. String format = GitBlit.getString(Keys.web.datestampShortFormat, "MM/dd/yy");
  132. final DateFormat df = new SimpleDateFormat(format);
  133. df.setTimeZone(getTimeZone());
  134. Fragment fragment = new Fragment(wicketId, fragmentId, this);
  135. List<RepoListItem> list = new ArrayList<RepoListItem>();
  136. for (RepositoryModel repo : repositories) {
  137. String name = StringUtils.stripDotGit(repo.name);
  138. String path = "";
  139. if (name.indexOf('/') > -1) {
  140. path = name.substring(0, name.lastIndexOf('/') + 1);
  141. name = name.substring(name.lastIndexOf('/') + 1);
  142. }
  143. RepoListItem item = new RepoListItem();
  144. item.n = name;
  145. item.p = path;
  146. item.r = repo.name;
  147. item.i = repo.description;
  148. item.s = GitBlit.self().getStarCount(repo);
  149. item.t = getTimeUtils().timeAgo(repo.lastChange);
  150. item.d = df.format(repo.lastChange);
  151. item.c = StringUtils.getColor(StringUtils.stripDotGit(repo.name));
  152. item.wc = repo.isBare ? 0 : 1;
  153. list.add(item);
  154. }
  155. // inject an AngularJS controller with static data
  156. NgController ctrl = new NgController(ngController);
  157. ctrl.addVariable(wicketId, list);
  158. add(new HeaderContributor(ctrl));
  159. return fragment;
  160. }
  161. @Override
  162. protected void addDropDownMenus(List<PageRegistration> pages) {
  163. PageParameters params = getPageParameters();
  164. DropDownMenuRegistration menu = new DropDownMenuRegistration("gb.filters",
  165. GitBlitWebApp.HOME_PAGE_CLASS);
  166. // preserve time filter option on repository choices
  167. menu.menuItems.addAll(getRepositoryFilterItems(params));
  168. // preserve repository filter option on time choices
  169. menu.menuItems.addAll(getTimeFilterItems(params));
  170. if (menu.menuItems.size() > 0) {
  171. // Reset Filter
  172. menu.menuItems.add(new DropDownMenuItem(getString("gb.reset"), null, null));
  173. }
  174. pages.add(menu);
  175. }
  176. /**
  177. * Creates the daily activity line chart, the active repositories pie chart,
  178. * and the active authors pie chart
  179. *
  180. * @param recentChanges
  181. * @param authorExclusions
  182. * @param daysBack
  183. */
  184. protected void addCharts(Fragment frag, List<DailyLogEntry> recentChanges, Set<String> authorExclusions, int daysBack) {
  185. // activity metrics
  186. Map<String, Metric> repositoryMetrics = new HashMap<String, Metric>();
  187. Map<String, Metric> authorMetrics = new HashMap<String, Metric>();
  188. // aggregate repository and author metrics
  189. int totalCommits = 0;
  190. for (RefLogEntry change : recentChanges) {
  191. // aggregate repository metrics
  192. String repository = StringUtils.stripDotGit(change.repository);
  193. if (!repositoryMetrics.containsKey(repository)) {
  194. repositoryMetrics.put(repository, new Metric(repository));
  195. }
  196. repositoryMetrics.get(repository).count += 1;
  197. for (RepositoryCommit commit : change.getCommits()) {
  198. totalCommits++;
  199. String author = StringUtils.removeNewlines(commit.getAuthorIdent().getName());
  200. String authorName = author.toLowerCase();
  201. String authorEmail = StringUtils.removeNewlines(commit.getAuthorIdent().getEmailAddress()).toLowerCase();
  202. if (!authorExclusions.contains(authorName) && !authorExclusions.contains(authorEmail)) {
  203. if (!authorMetrics.containsKey(author)) {
  204. authorMetrics.put(author, new Metric(author));
  205. }
  206. authorMetrics.get(author).count += 1;
  207. }
  208. }
  209. }
  210. String headerPattern;
  211. if (daysBack == 1) {
  212. // today
  213. if (totalCommits == 0) {
  214. headerPattern = getString("gb.todaysActivityNone");
  215. } else {
  216. headerPattern = getString("gb.todaysActivityStats");
  217. }
  218. } else {
  219. // multiple days
  220. if (totalCommits == 0) {
  221. headerPattern = getString("gb.recentActivityNone");
  222. } else {
  223. headerPattern = getString("gb.recentActivityStats");
  224. }
  225. }
  226. frag.add(new Label("feedheader", MessageFormat.format(headerPattern,
  227. daysBack, totalCommits, authorMetrics.size())));
  228. // build google charts
  229. GoogleCharts charts = new GoogleCharts();
  230. // active repositories pie chart
  231. GoogleChart chart = new GooglePieChart("chartRepositories", getString("gb.activeRepositories"),
  232. getString("gb.repository"), getString("gb.commits"));
  233. for (Metric metric : repositoryMetrics.values()) {
  234. chart.addValue(metric.name, metric.count);
  235. }
  236. chart.setShowLegend(false);
  237. charts.addChart(chart);
  238. // active authors pie chart
  239. chart = new GooglePieChart("chartAuthors", getString("gb.activeAuthors"),
  240. getString("gb.author"), getString("gb.commits"));
  241. for (Metric metric : authorMetrics.values()) {
  242. chart.addValue(metric.name, metric.count);
  243. }
  244. chart.setShowLegend(false);
  245. charts.addChart(chart);
  246. add(new HeaderContributor(charts));
  247. frag.add(new Fragment("charts", "chartsFragment", this));
  248. }
  249. protected class RepoListItem implements Serializable {
  250. private static final long serialVersionUID = 1L;
  251. String r; // repository
  252. String n; // name
  253. String p; // project/path
  254. String t; // time ago
  255. String d; // last updated
  256. String i; // information/description
  257. long s; // stars
  258. String c; // html color
  259. int wc; // working copy, 1 = true
  260. }
  261. }