summaryrefslogtreecommitdiffstats
path: root/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
diff options
context:
space:
mode:
Diffstat (limited to 'gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java')
-rw-r--r--gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java300
1 files changed, 218 insertions, 82 deletions
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
index a20b02ec89..09716cc7cd 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ApprovalTable.java
@@ -14,6 +14,8 @@
package com.google.gerrit.client.changes;
+import com.google.gerrit.client.ConfirmationCallback;
+import com.google.gerrit.client.ConfirmationDialog;
import com.google.gerrit.client.ErrorDialog;
import com.google.gerrit.client.FormatUtil;
import com.google.gerrit.client.Gerrit;
@@ -21,16 +23,17 @@ import com.google.gerrit.client.patches.PatchUtil;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountDashboardLink;
import com.google.gerrit.client.ui.AddMemberBox;
+import com.google.gerrit.client.ui.ReviewerSuggestOracle;
import com.google.gerrit.common.data.AccountInfoCache;
import com.google.gerrit.common.data.ApprovalDetail;
import com.google.gerrit.common.data.ApprovalType;
+import com.google.gerrit.common.data.ApprovalTypes;
import com.google.gerrit.common.data.ChangeDetail;
import com.google.gerrit.common.data.ReviewerResult;
-import com.google.gerrit.reviewdb.Account;
-import com.google.gerrit.reviewdb.ApprovalCategory;
-import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.common.data.SubmitRecord;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
@@ -38,33 +41,35 @@ import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.PushButton;
import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
/** Displays a table of {@link ApprovalDetail} objects for a change record. */
public class ApprovalTable extends Composite {
- private final List<ApprovalType> types;
+ private final ApprovalTypes types;
private final Grid table;
private final Widget missing;
private final Panel addReviewer;
+ private final ReviewerSuggestOracle reviewerSuggestOracle;
private final AddMemberBox addMemberBox;
private Change.Id changeId;
private AccountInfoCache accountCache = AccountInfoCache.empty();
public ApprovalTable() {
- types = Gerrit.getConfig().getApprovalTypes().getApprovalTypes();
- table = new Grid(1, 3 + types.size());
+ types = Gerrit.getConfig().getApprovalTypes();
+ table = new Grid(1, 3);
table.addStyleName(Gerrit.RESOURCES.css().infoTable());
- displayHeader();
missing = new Widget() {
{
@@ -75,8 +80,10 @@ public class ApprovalTable extends Composite {
addReviewer = new FlowPanel();
addReviewer.setStyleName(Gerrit.RESOURCES.css().addReviewer());
- addMemberBox = new AddMemberBox();
- addMemberBox.setAddButtonText(Util.C.approvalTableAddReviewer());
+ reviewerSuggestOracle = new ReviewerSuggestOracle();
+ addMemberBox =
+ new AddMemberBox(Util.C.approvalTableAddReviewer(),
+ Util.C.approvalTableAddReviewerHint(), reviewerSuggestOracle);
addMemberBox.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
@@ -95,7 +102,9 @@ public class ApprovalTable extends Composite {
setStyleName(Gerrit.RESOURCES.css().approvalTable());
}
- private void displayHeader() {
+ private void displayHeader(List<String> labels) {
+ table.resizeColumns(2 + labels.size());
+
final CellFormatter fmt = table.getCellFormatter();
int col = 0;
@@ -107,16 +116,12 @@ public class ApprovalTable extends Composite {
fmt.setStyleName(0, col, Gerrit.RESOURCES.css().header());
col++;
- for (final ApprovalType t : types) {
- table.setText(0, col, t.getCategory().getName());
+ for (String name : labels) {
+ table.setText(0, col, name);
fmt.setStyleName(0, col, Gerrit.RESOURCES.css().header());
col++;
}
-
- table.clearCell(0, col);
- fmt.setStyleName(0, col, Gerrit.RESOURCES.css().header());
- fmt.addStyleName(0, col, Gerrit.RESOURCES.css().rightmost());
- col++;
+ fmt.addStyleName(0, col - 1, Gerrit.RESOURCES.css().rightmost());
}
public void setAccountInfoCache(final AccountInfoCache aic) {
@@ -128,64 +133,160 @@ public class ApprovalTable extends Composite {
return AccountDashboardLink.link(accountCache, id);
}
- public void display(final Change change, final Set<ApprovalCategory.Id> need,
- final List<ApprovalDetail> rows) {
- changeId = change.getId();
+ void display(ChangeDetail detail) {
+ changeId = detail.getChange().getId();
+ reviewerSuggestOracle.setChange(changeId);
+
+ List<String> columns = new ArrayList<String>();
+ List<ApprovalDetail> rows = detail.getApprovals();
+
+ final Element missingList = missing.getElement();
+ while (DOM.getChildCount(missingList) > 0) {
+ DOM.removeChild(missingList, DOM.getChild(missingList, 0));
+ }
+ missing.setVisible(false);
+
+ if (detail.getSubmitRecords() != null) {
+ HashSet<String> reportedMissing = new HashSet<String>();
+
+ HashMap<Account.Id, ApprovalDetail> byUser =
+ new HashMap<Account.Id, ApprovalDetail>();
+ for (ApprovalDetail ad : detail.getApprovals()) {
+ byUser.put(ad.getAccount(), ad);
+ }
+
+ for (SubmitRecord rec : detail.getSubmitRecords()) {
+ if (rec.labels == null) {
+ continue;
+ }
+
+ for (SubmitRecord.Label lbl : rec.labels) {
+ if (!columns.contains(lbl.label)) {
+ columns.add(lbl.label);
+ }
+
+ switch (lbl.status) {
+ case OK: {
+ ApprovalDetail ad = byUser.get(lbl.appliedBy);
+ if (ad != null) {
+ ad.approved(lbl.label);
+ }
+ break;
+ }
+
+ case REJECT: {
+ ApprovalDetail ad = byUser.get(lbl.appliedBy);
+ if (ad != null) {
+ ad.rejected(lbl.label);
+ }
+ break;
+ }
+
+ case NEED:
+ case IMPOSSIBLE:
+ if (reportedMissing.add(lbl.label)) {
+ Element li = DOM.createElement("li");
+ li.setClassName(Gerrit.RESOURCES.css().missingApproval());
+ DOM.setInnerText(li, Util.M.needApproval(lbl.label));
+ DOM.appendChild(missingList, li);
+ }
+ break;
+ }
+ }
+ }
+ missing.setVisible(!reportedMissing.isEmpty());
+
+ } else {
+ for (ApprovalDetail ad : rows) {
+ for (PatchSetApproval psa : ad.getPatchSetApprovals()) {
+ ApprovalType legacyType = types.byId(psa.getCategoryId());
+ if (legacyType == null) {
+ continue;
+ }
+ String labelName = legacyType.getCategory().getLabelName();
+ if (psa.getValue() == legacyType.getMax().getValue()) {
+ ad.approved(labelName);
+ } else if (psa.getValue() == legacyType.getMin().getValue()) {
+ ad.rejected(labelName);
+ }
+ if (!columns.contains(labelName)) {
+ columns.add(labelName);
+ }
+ }
+ Collections.sort(columns, new Comparator<String>() {
+ @Override
+ public int compare(String o1, String o2) {
+ ApprovalType a = types.byLabel(o1);
+ ApprovalType b = types.byLabel(o2);
+ int cmp = 0;
+ if (a != null && b != null) {
+ cmp = a.getCategory().getPosition() - b.getCategory().getPosition();
+ }
+ if (cmp == 0) {
+ cmp = o1.compareTo(o2);
+ }
+ return cmp;
+ }
+ });
+ }
+ }
if (rows.isEmpty()) {
table.setVisible(false);
} else {
+ displayHeader(columns);
table.resizeRows(1 + rows.size());
for (int i = 0; i < rows.size(); i++) {
- displayRow(i + 1, rows.get(i), change);
+ displayRow(i + 1, rows.get(i), detail.getChange(), columns);
}
table.setVisible(true);
}
- final Element missingList = missing.getElement();
- while (DOM.getChildCount(missingList) > 0) {
- DOM.removeChild(missingList, DOM.getChild(missingList, 0));
- }
+ addReviewer.setVisible(Gerrit.isSignedIn());
- missing.setVisible(false);
- if (need != null) {
- for (final ApprovalType at : types) {
- if (need.contains(at.getCategory().getId())) {
- final Element li = DOM.createElement("li");
- li.setClassName(Gerrit.RESOURCES.css().missingApproval());
- DOM.setInnerText(li, Util.M.needApproval(at.getCategory().getName(),
- at.getMax().formatValue(), at.getMax().getName()));
- DOM.appendChild(missingList, li);
- missing.setVisible(true);
- }
- }
+ if (Gerrit.getConfig().testChangeMerge()
+ && !detail.getChange().isMergeable()) {
+ Element li = DOM.createElement("li");
+ li.setClassName(Gerrit.RESOURCES.css().missingApproval());
+ DOM.setInnerText(li, Util.C.messageNeedsRebaseOrHasDependency());
+ DOM.appendChild(missingList, li);
+ missing.setVisible(true);
}
-
- addReviewer.setVisible(Gerrit.isSignedIn() && change.getStatus().isOpen());
}
private void doAddReviewer() {
- final String nameEmail = addMemberBox.getText();
- if (nameEmail.length() == 0) {
+ final String reviewer = addMemberBox.getText();
+ if (reviewer.length() == 0) {
return;
}
addMemberBox.setEnabled(false);
final List<String> reviewers = new ArrayList<String>();
- reviewers.add(nameEmail);
+ reviewers.add(reviewer);
- PatchUtil.DETAIL_SVC.addReviewers(changeId, reviewers,
+ addReviewers(reviewers, false);
+ }
+
+ private void addReviewers(final List<String> reviewers,
+ final boolean confirmed) {
+ PatchUtil.DETAIL_SVC.addReviewers(changeId, reviewers, confirmed,
new GerritCallback<ReviewerResult>() {
public void onSuccess(final ReviewerResult result) {
addMemberBox.setEnabled(true);
addMemberBox.setText("");
+ final ChangeDetail changeDetail = result.getChange();
+ if (changeDetail != null) {
+ setAccountInfoCache(changeDetail.getAccounts());
+ display(changeDetail);
+ }
+
if (!result.getErrors().isEmpty()) {
final SafeHtmlBuilder r = new SafeHtmlBuilder();
for (final ReviewerResult.Error e : result.getErrors()) {
switch (e.getType()) {
- case ACCOUNT_NOT_FOUND:
- r.append(Util.M.accountNotFound(e.getName()));
+ case REVIEWER_NOT_FOUND:
+ r.append(Util.M.reviewerNotFound(e.getName()));
break;
case ACCOUNT_INACTIVE:
@@ -196,6 +297,23 @@ public class ApprovalTable extends Composite {
r.append(Util.M.changeNotVisibleTo(e.getName()));
break;
+ case GROUP_EMPTY:
+ r.append(Util.M.groupIsEmpty(e.getName()));
+ break;
+
+ case GROUP_HAS_TOO_MANY_MEMBERS:
+ if (result.askForConfirmation() && !confirmed) {
+ askForConfirmation(e.getName(), result.getMemberCount());
+ return;
+ } else {
+ r.append(Util.M.groupHasTooManyMembers(e.getName()));
+ }
+ break;
+
+ case GROUP_NOT_ALLOWED:
+ r.append(Util.M.groupIsNotAllowed(e.getName()));
+ break;
+
default:
r.append(e.getName());
r.append(" - ");
@@ -206,12 +324,25 @@ public class ApprovalTable extends Composite {
}
new ErrorDialog(r).center();
}
+ }
- final ChangeDetail r = result.getChange();
- if (r != null) {
- setAccountInfoCache(r.getAccounts());
- display(r.getChange(), r.getMissingApprovals(), r.getApprovals());
- }
+ private void askForConfirmation(final String groupName,
+ final int memberCount) {
+ final SafeHtmlBuilder b = new SafeHtmlBuilder();
+ b.openElement("b");
+ b.append(Util.M
+ .groupManyMembersConfirmation(groupName, memberCount));
+ b.closeElement("b");
+ final ConfirmationDialog confirmationDialog =
+ new ConfirmationDialog(Util.C
+ .approvalTableAddManyReviewersConfirmationDialogTitle(),
+ b.toSafeHtml(), new ConfirmationCallback() {
+ @Override
+ public void onOk() {
+ addReviewers(reviewers, true);
+ }
+ });
+ confirmationDialog.center();
}
@Override
@@ -223,10 +354,8 @@ public class ApprovalTable extends Composite {
}
private void displayRow(final int row, final ApprovalDetail ad,
- final Change change) {
+ final Change change, List<String> columns) {
final CellFormatter fmt = table.getCellFormatter();
- final Map<ApprovalCategory.Id, PatchSetApproval> am = ad.getApprovalMap();
- final StringBuilder hint = new StringBuilder();
int col = 0;
table.setWidget(row, col++, link(ad.getAccount()));
@@ -250,31 +379,30 @@ public class ApprovalTable extends Composite {
}
fmt.setStyleName(row, col++, Gerrit.RESOURCES.css().removeReviewerCell());
- for (final ApprovalType type : types) {
+ for (String labelName : columns) {
fmt.setStyleName(row, col, Gerrit.RESOURCES.css().approvalscore());
- final PatchSetApproval ca = am.get(type.getCategory().getId());
- if (ca == null || ca.getValue() == 0) {
- table.clearCell(row, col);
- col++;
- continue;
- }
-
- final ApprovalCategoryValue acv = type.getValue(ca);
- if (acv != null) {
- if (hint.length() > 0) {
- hint.append("; ");
- }
- hint.append(acv.getName());
- }
-
- if (type.isMaxNegative(ca)) {
+ if (ad.isRejected(labelName)) {
table.setWidget(row, col, new Image(Gerrit.RESOURCES.redNot()));
- } else if (type.isMaxPositive(ca)) {
+ } else if (ad.isApproved(labelName)) {
table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));
} else {
+ ApprovalType legacyType = types.byLabel(labelName);
+ if (legacyType == null) {
+ table.clearCell(row, col);
+ col++;
+ continue;
+ }
+
+ PatchSetApproval ca = ad.getPatchSetApproval(legacyType.getCategory().getId());
+ if (ca == null || ca.getValue() == 0) {
+ table.clearCell(row, col);
+ col++;
+ continue;
+ }
+
String vstr = String.valueOf(ca.getValue());
if (ca.getValue() > 0) {
vstr = "+" + vstr;
@@ -288,10 +416,7 @@ public class ApprovalTable extends Composite {
col++;
}
- table.setText(row, col, hint.toString());
- fmt.setStyleName(row, col, Gerrit.RESOURCES.css().rightmost());
- fmt.addStyleName(row, col, Gerrit.RESOURCES.css().approvalhint());
- col++;
+ fmt.addStyleName(row, col - 1, Gerrit.RESOURCES.css().rightmost());
}
private void doRemove(final ApprovalDetail ad, final PushButton remove) {
@@ -302,9 +427,20 @@ public class ApprovalTable extends Composite {
public void onSuccess(ReviewerResult result) {
if (result.getErrors().isEmpty()) {
final ChangeDetail r = result.getChange();
- display(r.getChange(), r.getMissingApprovals(), r.getApprovals());
+ display(r);
} else {
- new ErrorDialog(result.getErrors().get(0).toString()).center();
+ final ReviewerResult.Error resultError =
+ result.getErrors().get(0);
+ String message;
+ switch (resultError.getType()) {
+ case REMOVE_NOT_PERMITTED:
+ message = Util.C.approvalTableRemoveNotPermitted();
+ break;
+ case COULD_NOT_REMOVE:
+ default:
+ message = Util.C.approvalTableCouldNotRemove();
+ }
+ new ErrorDialog(message + " " + resultError.getName()).center();
}
}