Visualize sizes of changes in change tables and user dashboards

Add a new column to change tables and user dashboards in which the
size of a change is visualized by a colored bar. For small changes a
short green bar is shown, for medium sized changes a middle sized
yellow bar is shown and large changes have a full red bar.

Visualizing the change sizes gives a hint to the reviewers about how
complex a change is and how long it will take to review it.

For contributors the visualization of the change size may be a
motivation to split large changes into smaller pieces which will speed
up the review process.

How many changed lines are considered as a large change is
configurable.

Change-Id: I88497b8aea00047d93ad7d079eecc5e1052187d2
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
This commit is contained in:
Edwin Kempin
2013-11-23 12:50:29 +01:00
committed by Shawn Pearce
parent 4bb665eb8b
commit 662e55f6af
11 changed files with 78 additions and 6 deletions

View File

@@ -770,6 +770,17 @@ Default is 5 minutes.
[[change]]Section change [[change]]Section change
~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~
[[change.largeChange]]change.largeChange::
+
Number of changed lines from which on a change is considered as a large
change. The number of changed lines of a change is the sum of the lines
that were inserted and deleted in the change.
+
The specified value is used to visualize the change sizes in the web UI
in change tables and user dashboards.
+
By default 500.
[[change.updateDelay]]change.updateDelay:: [[change.updateDelay]]change.updateDelay::
+ +
How often in seconds the web interface should poll for updates to the How often in seconds the web interface should poll for updates to the

View File

@@ -54,6 +54,7 @@ public class GerritConfig implements Cloneable {
protected int changeUpdateDelay; protected int changeUpdateDelay;
protected AccountGeneralPreferences.ChangeScreen changeScreen; protected AccountGeneralPreferences.ChangeScreen changeScreen;
protected boolean index; protected boolean index;
protected int largeChangeSize;
public String getLoginUrl() { public String getLoginUrl() {
return loginUrl; return loginUrl;
@@ -289,4 +290,12 @@ public class GerritConfig implements Cloneable {
public void setIndex(boolean index) { public void setIndex(boolean index) {
this.index = index; this.index = index;
} }
public int getLargeChangeSize() {
return largeChangeSize;
}
public void setLargeChangeSize(int largeChangeSize) {
this.largeChangeSize = largeChangeSize;
}
} }

View File

@@ -41,6 +41,7 @@ public interface GerritCss extends CssResource {
String cAPPROVAL(); String cAPPROVAL();
String cLastUpdate(); String cLastUpdate();
String cOWNER(); String cOWNER();
String cSIZE();
String cSUBJECT(); String cSUBJECT();
String cellsNextToFileComment(); String cellsNextToFileComment();
String changeComments(); String changeComments();
@@ -49,6 +50,7 @@ public interface GerritCss extends CssResource {
String changeScreen(); String changeScreen();
String changeScreenDescription(); String changeScreenDescription();
String changeScreenStarIcon(); String changeScreenStarIcon();
String changeSize();
String changeTable(); String changeTable();
String changeTablePrevNextLinks(); String changeTablePrevNextLinks();
String changeTypeCell(); String changeTypeCell();

View File

@@ -40,6 +40,7 @@ public interface ChangeConstants extends Constants {
String allMergedChanges(); String allMergedChanges();
String changeTableColumnSubject(); String changeTableColumnSubject();
String changeTableColumnSize();
String changeTableColumnStatus(); String changeTableColumnStatus();
String changeTableColumnOwner(); String changeTableColumnOwner();
String changeTableColumnReviewers(); String changeTableColumnReviewers();

View File

@@ -20,6 +20,7 @@ allAbandonedChanges = All abandoned changes
allMergedChanges = All merged changes allMergedChanges = All merged changes
changeTableColumnSubject = Subject changeTableColumnSubject = Subject
changeTableColumnSize = Size
changeTableColumnStatus = Status changeTableColumnStatus = Status
changeTableColumnOwner = Owner changeTableColumnOwner = Owner
changeTableColumnReviewers = Reviewers changeTableColumnReviewers = Reviewers

View File

@@ -85,6 +85,8 @@ public class ChangeInfo extends JavaScriptObject {
public final native String topic() /*-{ return this.topic; }-*/; public final native String topic() /*-{ return this.topic; }-*/;
public final native String change_id() /*-{ return this.change_id; }-*/; public final native String change_id() /*-{ return this.change_id; }-*/;
public final native boolean mergeable() /*-{ return this.mergeable; }-*/; public final native boolean mergeable() /*-{ return this.mergeable; }-*/;
public final native int insertions() /*-{ return this.insertions; }-*/;
public final native int deletions() /*-{ return this.deletions; }-*/;
private final native String statusRaw() /*-{ return this.status; }-*/; private final native String statusRaw() /*-{ return this.status; }-*/;
public final native String subject() /*-{ return this.subject; }-*/; public final native String subject() /*-{ return this.subject; }-*/;
public final native AccountInfo owner() /*-{ return this.owner; }-*/; public final native AccountInfo owner() /*-{ return this.owner; }-*/;

View File

@@ -69,4 +69,6 @@ public interface ChangeMessages extends Messages {
String years0MonthsAgo(long years, String yearLabel); String years0MonthsAgo(long years, String yearLabel);
String yearsMonthsAgo(long years, String yearLabel, long months, String yearsMonthsAgo(long years, String yearLabel, long months,
String monthLabel); String monthLabel);
String insertionsAndDeletions(int insertions, int deletions);
} }

View File

@@ -51,3 +51,5 @@ monthsAgo = {0} months ago
years0MonthsAgo = {0} {1} ago years0MonthsAgo = {0} {1} ago
yearsMonthsAgo = {0} {1}, {2} {3} ago yearsMonthsAgo = {0} {1}, {2} {3} ago
yearsAgo = {0} years ago yearsAgo = {0} years ago
insertionsAndDeletions = +{0}, -{1}

View File

@@ -38,6 +38,7 @@ import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.InlineLabel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.UIObject;
import com.google.gwt.user.client.ui.Widget; import com.google.gwt.user.client.ui.Widget;
@@ -48,12 +49,13 @@ import java.util.List;
public class ChangeTable2 extends NavigationTable<ChangeInfo> { public class ChangeTable2 extends NavigationTable<ChangeInfo> {
private static final int C_STAR = 1; private static final int C_STAR = 1;
private static final int C_SUBJECT = 2; private static final int C_SUBJECT = 2;
private static final int C_STATUS = 3; private static final int C_SIZE = 3;
private static final int C_OWNER = 4; private static final int C_STATUS = 4;
private static final int C_PROJECT = 5; private static final int C_OWNER = 5;
private static final int C_BRANCH = 6; private static final int C_PROJECT = 6;
private static final int C_LAST_UPDATE = 7; private static final int C_BRANCH = 7;
private static final int BASE_COLUMNS = 8; private static final int C_LAST_UPDATE = 8;
private static final int BASE_COLUMNS = 9;
private final List<Section> sections; private final List<Section> sections;
private int columns; private int columns;
@@ -71,6 +73,7 @@ public class ChangeTable2 extends NavigationTable<ChangeInfo> {
sections = new ArrayList<Section>(); sections = new ArrayList<Section>();
table.setText(0, C_STAR, ""); table.setText(0, C_STAR, "");
table.setText(0, C_SUBJECT, Util.C.changeTableColumnSubject()); table.setText(0, C_SUBJECT, Util.C.changeTableColumnSubject());
table.setText(0, C_SIZE, Util.C.changeTableColumnSize());
table.setText(0, C_STATUS, Util.C.changeTableColumnStatus()); table.setText(0, C_STATUS, Util.C.changeTableColumnStatus());
table.setText(0, C_OWNER, Util.C.changeTableColumnOwner()); table.setText(0, C_OWNER, Util.C.changeTableColumnOwner());
table.setText(0, C_PROJECT, Util.C.changeTableColumnProject()); table.setText(0, C_PROJECT, Util.C.changeTableColumnProject());
@@ -137,6 +140,7 @@ public class ChangeTable2 extends NavigationTable<ChangeInfo> {
fmt.addStyleName(row, i, Gerrit.RESOURCES.css().dataCell()); fmt.addStyleName(row, i, Gerrit.RESOURCES.css().dataCell());
} }
fmt.addStyleName(row, C_SUBJECT, Gerrit.RESOURCES.css().cSUBJECT()); fmt.addStyleName(row, C_SUBJECT, Gerrit.RESOURCES.css().cSUBJECT());
fmt.addStyleName(row, C_SIZE, Gerrit.RESOURCES.css().cSIZE());
fmt.addStyleName(row, C_OWNER, Gerrit.RESOURCES.css().cOWNER()); fmt.addStyleName(row, C_OWNER, Gerrit.RESOURCES.css().cOWNER());
fmt.addStyleName(row, C_LAST_UPDATE, Gerrit.RESOURCES.css().cLastUpdate()); fmt.addStyleName(row, C_LAST_UPDATE, Gerrit.RESOURCES.css().cLastUpdate());
for (int i = BASE_COLUMNS; i < columns; i++) { for (int i = BASE_COLUMNS; i < columns; i++) {
@@ -197,6 +201,8 @@ public class ChangeTable2 extends NavigationTable<ChangeInfo> {
String subject = Util.cropSubject(c.subject()); String subject = Util.cropSubject(c.subject());
table.setWidget(row, C_SUBJECT, new TableChangeLink(subject, c)); table.setWidget(row, C_SUBJECT, new TableChangeLink(subject, c));
table.setWidget(row, C_SIZE, getSizeWidget(c));
Change.Status status = c.status(); Change.Status status = c.status();
if (status != Change.Status.NEW) { if (status != Change.Status.NEW) {
table.setText(row, C_STATUS, Util.toLongString(status)); table.setText(row, C_STATUS, Util.toLongString(status));
@@ -296,6 +302,32 @@ public class ChangeTable2 extends NavigationTable<ChangeInfo> {
setRowItem(row, c); setRowItem(row, c);
} }
private static Widget getSizeWidget(ChangeInfo c) {
int largeChangeSize = Gerrit.getConfig().getLargeChangeSize();
int changedLines = c.insertions() + c.deletions();
int p = 100;
if (changedLines < largeChangeSize) {
p = Math.round(changedLines * 100 / largeChangeSize);
}
int width = Math.max(2, 70 * p / 100);
int red = p > 50 ? 255 : (int) Math.round((p) * 5.12);
int green = p < 50 ? 255 : (int) Math.round(256 - (p - 50) * 5.12);
String bg = "#" + toHex(red) + toHex(green) + "00";
SimplePanel panel = new SimplePanel();
panel.setStyleName(Gerrit.RESOURCES.css().changeSize());
panel.setWidth(width + "px");
panel.getElement().getStyle().setBackgroundColor(bg);
panel.setTitle(Util.M.insertionsAndDeletions(c.insertions(), c.deletions()));
return panel;
}
private static String toHex(int i) {
String hex = Integer.toHexString(i);
return hex.length() == 1 ? "0" + hex : hex;
}
public void addSection(final Section s) { public void addSection(final Section s) {
assert s.parent == null; assert s.parent == null;

View File

@@ -538,6 +538,11 @@ a:hover {
color: #222 !important; color: #222 !important;
} }
.changeTable .changeSize {
height: 10px;
display: inline-block;
}
.accountDashboard.changeTable tr { .accountDashboard.changeTable tr {
color: #444444; color: #444444;
} }
@@ -557,6 +562,10 @@ a:hover {
background: selectionColor !important; background: selectionColor !important;
} }
.changeTable .cSIZE {
width: 70px;
}
.changeTable .cSUBJECT div { .changeTable .cSUBJECT div {
text-overflow: ellipsis; text-overflow: ellipsis;
overflow: hidden; overflow: hidden;

View File

@@ -133,6 +133,7 @@ class GerritConfigProvider implements Provider<GerritConfig> {
"gerrit", null, "changeScreen", "gerrit", null, "changeScreen",
AccountGeneralPreferences.ChangeScreen.CHANGE_SCREEN2)); AccountGeneralPreferences.ChangeScreen.CHANGE_SCREEN2));
config.setIndex(indexCollection.getSearchIndex() != null); config.setIndex(indexCollection.getSearchIndex() != null);
config.setLargeChangeSize(cfg.getInt("change", "largeChange", 500));
config.setReportBugUrl(cfg.getString("gerrit", null, "reportBugUrl")); config.setReportBugUrl(cfg.getString("gerrit", null, "reportBugUrl"));
if (config.getReportBugUrl() == null) { if (config.getReportBugUrl() == null) {