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.java452
1 files changed, 199 insertions, 253 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 73036ffb16..deb867ca43 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,27 +14,28 @@
package com.google.gerrit.client.changes;
+import static com.google.gerrit.common.data.LabelValue.formatValue;
+
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;
-import com.google.gerrit.client.patches.PatchUtil;
+import com.google.gerrit.client.account.AccountInfo;
+import com.google.gerrit.client.changes.ChangeInfo.ApprovalInfo;
+import com.google.gerrit.client.changes.ChangeInfo.LabelInfo;
import com.google.gerrit.client.rpc.GerritCallback;
+import com.google.gerrit.client.rpc.NativeMap;
+import com.google.gerrit.client.rpc.NativeString;
+import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.client.ui.AccountLink;
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.PatchSetPublishDetail;
-import com.google.gerrit.common.data.ReviewerResult;
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.core.client.JavaScriptObject;
+import com.google.gwt.core.client.JsArray;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.DOM;
@@ -50,25 +51,26 @@ import com.google.gwt.user.client.ui.Widget;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
+import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.LinkedHashMap;
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 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();
+ private ChangeInfo lastChange;
+ private Map<Integer, Integer> rows;
public ApprovalTable() {
- types = Gerrit.getConfig().getApprovalTypes();
+ rows = new HashMap<Integer, Integer>();
table = new Grid(1, 3);
table.addStyleName(Gerrit.RESOURCES.css().infoTable());
@@ -103,7 +105,7 @@ public class ApprovalTable extends Composite {
setStyleName(Gerrit.RESOURCES.css().approvalTable());
}
- private void displayHeader(List<String> labels) {
+ private void displayHeader(Collection<String> labels) {
table.resizeColumns(2 + labels.size());
final CellFormatter fmt = table.getCellFormatter();
@@ -125,264 +127,218 @@ public class ApprovalTable extends Composite {
fmt.addStyleName(0, col - 1, Gerrit.RESOURCES.css().rightmost());
}
- public void setAccountInfoCache(final AccountInfoCache aic) {
- assert aic != null;
- accountCache = aic;
- }
+ void display(ChangeInfo change) {
+ lastChange = change;
+ reviewerSuggestOracle.setChange(change.legacy_id());
+ Map<Integer, ApprovalDetail> byUser =
+ new LinkedHashMap<Integer, ApprovalDetail>();
+ Map<Integer, AccountInfo> accounts =
+ new LinkedHashMap<Integer, AccountInfo>();
+ List<String> missingLabels = initLabels(change, accounts, byUser);
+
+ removeAllChildren(missing.getElement());
+ for (String label : missingLabels) {
+ addMissingLabel(Util.M.needApproval(label));
+ }
- private AccountLink link(final Account.Id id) {
- return AccountLink.link(accountCache, id);
- }
+ if (byUser.isEmpty()) {
+ table.setVisible(false);
+ } else {
+ displayHeader(change.labels());
+ table.resizeRows(1 + byUser.size());
+ int i = 1;
+ for (ApprovalDetail ad : ApprovalDetail.sort(
+ byUser.values(), change.owner()._account_id())) {
+ displayRow(i++, ad, change, accounts.get(ad.getAccount().get()));
+ }
+ table.setVisible(true);
+ }
- void display(PatchSetPublishDetail detail) {
- doDisplay(detail.getChange(), detail.getApprovals(),
- detail.getSubmitRecords());
+ if (Gerrit.getConfig().testChangeMerge()
+ && change.status() != Change.Status.MERGED
+ && !change.mergeable()) {
+ addMissingLabel(Util.C.messageNeedsRebaseOrHasDependency());
+ }
+ missing.setVisible(DOM.getChildCount(missing.getElement()) > 0);
+ addReviewer.setVisible(Gerrit.isSignedIn());
}
- void display(ChangeDetail detail) {
- doDisplay(detail.getChange(), detail.getApprovals(),
- detail.getSubmitRecords());
+ private void removeAllChildren(Element el) {
+ for (int i = DOM.getChildCount(el) - 1; i >= 0; i--) {
+ DOM.removeChild(el, DOM.getChild(el, i));
+ }
}
- private void doDisplay(Change change, List<ApprovalDetail> approvals,
- List<SubmitRecord> submitRecords) {
- changeId = change.getId();
- reviewerSuggestOracle.setChange(changeId);
-
- List<String> columns = new ArrayList<String>();
+ private void addMissingLabel(String text) {
+ Element li = DOM.createElement("li");
+ li.setClassName(Gerrit.RESOURCES.css().missingApproval());
+ DOM.setInnerText(li, text);
+ DOM.appendChild(missing.getElement(), li);
+ }
- final Element missingList = missing.getElement();
- while (DOM.getChildCount(missingList) > 0) {
- DOM.removeChild(missingList, DOM.getChild(missingList, 0));
+ private Set<Integer> removableReviewers(ChangeInfo change) {
+ Set<Integer> result =
+ new HashSet<Integer>(change.removable_reviewers().length());
+ for (int i = 0; i < change.removable_reviewers().length(); i++) {
+ result.add(change.removable_reviewers().get(i)._account_id());
}
- missing.setVisible(false);
-
- if (submitRecords != null) {
- HashSet<String> reportedMissing = new HashSet<String>();
-
- HashMap<Account.Id, ApprovalDetail> byUser =
- new HashMap<Account.Id, ApprovalDetail>();
- for (ApprovalDetail ad : approvals) {
- byUser.put(ad.getAccount(), ad);
- }
+ return result;
+ }
- for (SubmitRecord rec : submitRecords) {
- if (rec.labels == null) {
- continue;
+ private List<String> initLabels(ChangeInfo change,
+ Map<Integer, AccountInfo> accounts,
+ Map<Integer, ApprovalDetail> byUser) {
+ Set<Integer> removableReviewers = removableReviewers(change);
+ List<String> missing = new ArrayList<String>();
+ for (String name : change.labels()) {
+ LabelInfo label = change.label(name);
+
+ String min = null;
+ String max = null;
+ for (String v : label.values()) {
+ if (min == null) {
+ min = v;
}
-
- 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 MAY:
- 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;
- }
+ if (v.startsWith("+")) {
+ max = v;
}
}
- missing.setVisible(!reportedMissing.isEmpty());
- } else {
- for (ApprovalDetail ad : approvals) {
- for (PatchSetApproval psa : ad.getPatchSetApprovals()) {
- ApprovalType legacyType = types.byId(psa.getCategoryId());
- if (legacyType == null) {
- continue;
- }
- String labelName = legacyType.getCategory().getLabelName();
- if (psa.getValue() != 0 ) {
- if (psa.getValue() == legacyType.getMax().getValue()) {
- ad.approved(labelName);
- } else if (psa.getValue() == legacyType.getMin().getValue()) {
- ad.rejected(labelName);
- }
+ if (label.status() == SubmitRecord.Label.Status.NEED) {
+ missing.add(name);
+ }
+
+ if (label.all() != null) {
+ for (ApprovalInfo ai : Natives.asList(label.all())) {
+ if (!accounts.containsKey(ai._account_id())) {
+ accounts.put(ai._account_id(), ai);
}
- if (!columns.contains(labelName)) {
- columns.add(labelName);
+ int id = ai._account_id();
+ ApprovalDetail ad = byUser.get(id);
+ if (ad == null) {
+ ad = new ApprovalDetail(new Account.Id(id));
+ ad.setCanRemove(removableReviewers.contains(id));
+ byUser.put(id, ad);
}
- }
- 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);
+ if (ai.has_value()) {
+ ad.votable(name);
+ ad.value(name, ai.value());
+ String fv = formatValue(ai.value());
+ if (fv.equals(max)) {
+ ad.approved(name);
+ } else if (ai.value() < 0 && fv.equals(min)) {
+ ad.rejected(name);
}
- return cmp;
}
- });
+ }
}
}
+ return missing;
+ }
- if (approvals.isEmpty()) {
- table.setVisible(false);
- } else {
- displayHeader(columns);
- table.resizeRows(1 + approvals.size());
- for (int i = 0; i < approvals.size(); i++) {
- displayRow(i + 1, approvals.get(i), change, columns);
- }
- table.setVisible(true);
+ private void doAddReviewer() {
+ String reviewer = addMemberBox.getText();
+ if (!reviewer.isEmpty()) {
+ addMemberBox.setEnabled(false);
+ addReviewer(reviewer, false);
}
+ }
- addReviewer.setVisible(Gerrit.isSignedIn());
+ private static class PostInput extends JavaScriptObject {
+ static PostInput create(String reviewer, boolean confirmed) {
+ PostInput input = createObject().cast();
+ input.init(reviewer, confirmed);
+ return input;
+ }
- if (Gerrit.getConfig().testChangeMerge()
- && !change.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);
+ private native void init(String reviewer, boolean confirmed) /*-{
+ this.reviewer = reviewer;
+ if (confirmed) {
+ this.confirmed = true;
+ }
+ }-*/;
+
+ protected PostInput() {
}
}
- private void doAddReviewer() {
- final String reviewer = addMemberBox.getText();
- if (reviewer.length() == 0) {
- return;
+ private static class ReviewerInfo extends AccountInfo {
+ final Set<String> approvals() {
+ return Natives.keys(_approvals());
}
+ final native String approval(String l) /*-{ return this.approvals[l]; }-*/;
+ private final native NativeMap<NativeString> _approvals() /*-{ return this.approvals; }-*/;
- addMemberBox.setEnabled(false);
- final List<String> reviewers = new ArrayList<String>();
- reviewers.add(reviewer);
+ protected ReviewerInfo() {
+ }
+ }
- addReviewers(reviewers, false);
+ private static class PostResult extends JavaScriptObject {
+ final native JsArray<ReviewerInfo> reviewers() /*-{ return this.reviewers; }-*/;
+ final native boolean confirm() /*-{ return this.confirm || false; }-*/;
+ final native String error() /*-{ return this.error; }-*/;
+
+ protected PostResult() {
+ }
}
- 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) {
+ private void addReviewer(final String reviewer, boolean confirmed) {
+ ChangeApi.reviewers(lastChange.legacy_id().get()).post(
+ PostInput.create(reviewer, confirmed),
+ new GerritCallback<PostResult>() {
+ public void onSuccess(PostResult 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 REVIEWER_NOT_FOUND:
- r.append(Util.M.reviewerNotFound(e.getName()));
- break;
-
- case ACCOUNT_INACTIVE:
- r.append(Util.M.accountInactive(e.getName()));
- break;
-
- case CHANGE_NOT_VISIBLE:
- 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(" - ");
- r.append(e.getType());
- r.br();
- break;
- }
- }
- new ErrorDialog(r).center();
+ if (result.error() == null) {
+ reload();
+ } else if (result.confirm()) {
+ askForConfirmation(result.error());
+ } else {
+ new ErrorDialog(new SafeHtmlBuilder().append(result.error()));
}
}
- 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);
- }
- });
+ private void askForConfirmation(String text) {
+ String title = Util.C
+ .approvalTableAddManyReviewersConfirmationDialogTitle();
+ ConfirmationDialog confirmationDialog = new ConfirmationDialog(
+ title, new SafeHtmlBuilder().append(text),
+ new ConfirmationCallback() {
+ @Override
+ public void onOk() {
+ addReviewer(reviewer, true);
+ }
+ });
confirmationDialog.center();
}
@Override
public void onFailure(final Throwable caught) {
addMemberBox.setEnabled(true);
- super.onFailure(caught);
+ if (isNoSuchEntity(caught)) {
+ new ErrorDialog(Util.M.reviewerNotFound(reviewer)).center();
+ } else {
+ super.onFailure(caught);
+ }
}
});
}
- private void displayRow(final int row, final ApprovalDetail ad,
- final Change change, List<String> columns) {
+ private void displayRow(int row, final ApprovalDetail ad, ChangeInfo change,
+ AccountInfo account) {
final CellFormatter fmt = table.getCellFormatter();
int col = 0;
- table.setWidget(row, col++, link(ad.getAccount()));
+ table.setWidget(row, col++, new AccountLink(account));
+ rows.put(account._account_id(), row);
if (ad.canRemove()) {
final PushButton remove = new PushButton( //
new Image(Util.R.removeReviewerNormal()), //
new Image(Util.R.removeReviewerPressed()));
- remove.setTitle(Util.M.removeReviewer( //
- FormatUtil.name(accountCache.get(ad.getAccount()))));
+ remove.setTitle(Util.M.removeReviewer(account.name()));
remove.setStyleName(Gerrit.RESOURCES.css().removeReviewer());
+ remove.addStyleName(Gerrit.RESOURCES.css().link());
remove.addClickHandler(new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
@@ -395,8 +351,12 @@ public class ApprovalTable extends Composite {
}
fmt.setStyleName(row, col++, Gerrit.RESOURCES.css().removeReviewerCell());
- for (String labelName : columns) {
+ for (String labelName : change.labels()) {
fmt.setStyleName(row, col, Gerrit.RESOURCES.css().approvalscore());
+ if (!ad.canVote(labelName)) {
+ fmt.addStyleName(row, col, Gerrit.RESOURCES.css().notVotable());
+ fmt.getElement(row, col).setTitle(Gerrit.C.userCannotVoteToolTip());
+ }
if (ad.isRejected(labelName)) {
table.setWidget(row, col, new Image(Gerrit.RESOURCES.redNot()));
@@ -405,22 +365,14 @@ public class ApprovalTable extends Composite {
table.setWidget(row, col, new Image(Gerrit.RESOURCES.greenCheck()));
} else {
- ApprovalType legacyType = types.byLabel(labelName);
- if (legacyType == null) {
+ int v = ad.getValue(labelName);
+ if (v == 0) {
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) {
+ String vstr = String.valueOf(ad.getValue(labelName));
+ if (v > 0) {
vstr = "+" + vstr;
fmt.addStyleName(row, col, Gerrit.RESOURCES.css().posscore());
} else {
@@ -435,29 +387,23 @@ public class ApprovalTable extends Composite {
fmt.addStyleName(row, col - 1, Gerrit.RESOURCES.css().rightmost());
}
- private void doRemove(final ApprovalDetail ad, final PushButton remove) {
+ private void reload() {
+ ChangeApi.detail(lastChange.legacy_id().get(),
+ new GerritCallback<ChangeInfo>() {
+ @Override
+ public void onSuccess(ChangeInfo result) {
+ display(result);
+ }
+ });
+ }
+
+ private void doRemove(ApprovalDetail ad, final PushButton remove) {
remove.setEnabled(false);
- PatchUtil.DETAIL_SVC.removeReviewer(changeId, ad.getAccount(),
- new GerritCallback<ReviewerResult>() {
+ ChangeApi.reviewer(lastChange.legacy_id().get(), ad.getAccount().get())
+ .delete(new GerritCallback<JavaScriptObject>() {
@Override
- public void onSuccess(ReviewerResult result) {
- if (result.getErrors().isEmpty()) {
- final ChangeDetail r = result.getChange();
- display(r);
- } else {
- 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();
- }
+ public void onSuccess(JavaScriptObject result) {
+ reload();
}
@Override