Allow RestApiView<RevisionResource> to add buttons on patch sets
RestApiViews that accept a RevisionResource may now also describe buttons that should appear on a patch set. Description is given to Gerrit by implementing the UiCommand interface and returning useful information from the getter methods. Change-Id: I2b9445e73448968f1e3234812cc28b57e9ec7250
This commit is contained in:
		@@ -19,6 +19,7 @@ import com.google.gerrit.reviewdb.client.PatchSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.PatchSetInfo;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Project;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
public class PatchSetDetail {
 | 
			
		||||
@@ -26,6 +27,7 @@ public class PatchSetDetail {
 | 
			
		||||
  protected PatchSetInfo info;
 | 
			
		||||
  protected List<Patch> patches;
 | 
			
		||||
  protected Project.NameKey project;
 | 
			
		||||
  protected List<UiCommandDetail> commands;
 | 
			
		||||
 | 
			
		||||
  public PatchSetDetail() {
 | 
			
		||||
  }
 | 
			
		||||
@@ -61,4 +63,15 @@ public class PatchSetDetail {
 | 
			
		||||
  public void setProject(final Project.NameKey p) {
 | 
			
		||||
    project = p;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public List<UiCommandDetail> getCommands() {
 | 
			
		||||
    if (commands != null) {
 | 
			
		||||
      return commands;
 | 
			
		||||
    }
 | 
			
		||||
    return Collections.emptyList();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void setCommands(List<UiCommandDetail> cmds) {
 | 
			
		||||
    commands = cmds;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,24 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.common.data;
 | 
			
		||||
 | 
			
		||||
/** Detail necessary to display an action. */
 | 
			
		||||
public class UiCommandDetail {
 | 
			
		||||
  public String id;
 | 
			
		||||
  public String method;
 | 
			
		||||
  public String label;
 | 
			
		||||
  public String title;
 | 
			
		||||
  public boolean enabled;
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,30 @@
 | 
			
		||||
// Copyright (C) 2013 The Android Open Source Project
 | 
			
		||||
//
 | 
			
		||||
// Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
// you may not use this file except in compliance with the License.
 | 
			
		||||
// You may obtain a copy of the License at
 | 
			
		||||
//
 | 
			
		||||
// http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
//
 | 
			
		||||
// Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
// distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.extensions.webui;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestResource;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestView;
 | 
			
		||||
 | 
			
		||||
public interface UiCommand<R extends RestResource> extends RestView<R> {
 | 
			
		||||
  public static enum Place {
 | 
			
		||||
    PATCHSET_ACTION_PANEL;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  Place getPlace();
 | 
			
		||||
  String getLabel(R resource);
 | 
			
		||||
  String getTitle(R resource);
 | 
			
		||||
  boolean isVisible(R resource);
 | 
			
		||||
  boolean isEnabled(R resource);
 | 
			
		||||
}
 | 
			
		||||
@@ -14,12 +14,15 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.client.changes;
 | 
			
		||||
import com.google.gerrit.client.Dispatcher;
 | 
			
		||||
import com.google.gerrit.client.ErrorDialog;
 | 
			
		||||
import com.google.gerrit.client.FormatUtil;
 | 
			
		||||
import com.google.gerrit.client.Gerrit;
 | 
			
		||||
import com.google.gerrit.client.GitwebLink;
 | 
			
		||||
import com.google.gerrit.client.download.DownloadPanel;
 | 
			
		||||
import com.google.gerrit.client.patches.PatchUtil;
 | 
			
		||||
import com.google.gerrit.client.rpc.GerritCallback;
 | 
			
		||||
import com.google.gerrit.client.rpc.NativeString;
 | 
			
		||||
import com.google.gerrit.client.rpc.RestApi;
 | 
			
		||||
import com.google.gerrit.client.ui.AccountLinkPanel;
 | 
			
		||||
import com.google.gerrit.client.ui.ActionDialog;
 | 
			
		||||
import com.google.gerrit.client.ui.CherryPickDialog;
 | 
			
		||||
@@ -28,6 +31,7 @@ import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
 | 
			
		||||
import com.google.gerrit.common.PageLinks;
 | 
			
		||||
import com.google.gerrit.common.data.ChangeDetail;
 | 
			
		||||
import com.google.gerrit.common.data.PatchSetDetail;
 | 
			
		||||
import com.google.gerrit.common.data.UiCommandDetail;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadCommand;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountGeneralPreferences.DownloadScheme;
 | 
			
		||||
@@ -35,10 +39,13 @@ import com.google.gerrit.reviewdb.client.Change;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.PatchSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.PatchSetInfo;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.UserIdentity;
 | 
			
		||||
import com.google.gwt.core.client.JavaScriptObject;
 | 
			
		||||
import com.google.gwt.event.dom.client.ClickEvent;
 | 
			
		||||
import com.google.gwt.event.dom.client.ClickHandler;
 | 
			
		||||
import com.google.gwt.event.logical.shared.OpenEvent;
 | 
			
		||||
import com.google.gwt.event.logical.shared.OpenHandler;
 | 
			
		||||
import com.google.gwt.user.client.Window;
 | 
			
		||||
import com.google.gwt.user.client.rpc.AsyncCallback;
 | 
			
		||||
import com.google.gwt.user.client.ui.Anchor;
 | 
			
		||||
import com.google.gwt.user.client.ui.Button;
 | 
			
		||||
import com.google.gwt.user.client.ui.DisclosurePanel;
 | 
			
		||||
@@ -169,6 +176,7 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel
 | 
			
		||||
          if (changeDetail.isCurrentPatchSet(detail)) {
 | 
			
		||||
            populateActions(detail);
 | 
			
		||||
          }
 | 
			
		||||
          populateCommands(detail);
 | 
			
		||||
        }
 | 
			
		||||
        if (detail.getPatchSet().isDraft()) {
 | 
			
		||||
          if (changeDetail.canPublish()) {
 | 
			
		||||
@@ -535,6 +543,45 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void populateCommands(final PatchSetDetail detail) {
 | 
			
		||||
    for (final UiCommandDetail cmd : detail.getCommands()) {
 | 
			
		||||
      final Button b = new Button(cmd.label);
 | 
			
		||||
      b.setEnabled(cmd.enabled);
 | 
			
		||||
      b.setTitle(cmd.title);
 | 
			
		||||
      b.addClickHandler(new ClickHandler() {
 | 
			
		||||
        @Override
 | 
			
		||||
        public void onClick(final ClickEvent event) {
 | 
			
		||||
          b.setEnabled(false);
 | 
			
		||||
          AsyncCallback<NativeString> cb =
 | 
			
		||||
              new AsyncCallback<NativeString>() {
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onFailure(Throwable caught) {
 | 
			
		||||
                  b.setEnabled(true);
 | 
			
		||||
                  new ErrorDialog(caught).center();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                @Override
 | 
			
		||||
                public void onSuccess(NativeString msg) {
 | 
			
		||||
                  b.setEnabled(true);
 | 
			
		||||
                  if (msg != null) {
 | 
			
		||||
                    Window.alert(msg.asString());
 | 
			
		||||
                  }
 | 
			
		||||
                }
 | 
			
		||||
              };
 | 
			
		||||
          RestApi api = ChangeApi.revision(patchSet.getId()).view(cmd.id);
 | 
			
		||||
          if ("PUT".equalsIgnoreCase(cmd.method)) {
 | 
			
		||||
            api.put(JavaScriptObject.createObject(), cb);
 | 
			
		||||
          } else if ("DELETE".equalsIgnoreCase(cmd.method)) {
 | 
			
		||||
            api.delete(cb);
 | 
			
		||||
          } else {
 | 
			
		||||
            api.post(JavaScriptObject.createObject(), cb);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      actionsPanel.add(b);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private void populateReviewAction() {
 | 
			
		||||
    final Button b = new Button(Util.C.buttonReview());
 | 
			
		||||
    b.addClickHandler(new ClickHandler() {
 | 
			
		||||
 
 | 
			
		||||
@@ -14,20 +14,28 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.httpd.rpc.changedetail;
 | 
			
		||||
 | 
			
		||||
import com.google.common.collect.Lists;
 | 
			
		||||
import com.google.gerrit.common.data.PatchSetDetail;
 | 
			
		||||
import com.google.gerrit.common.data.UiCommandDetail;
 | 
			
		||||
import com.google.gerrit.common.errors.NoSuchEntityException;
 | 
			
		||||
import com.google.gerrit.extensions.registration.DynamicMap;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestView;
 | 
			
		||||
import com.google.gerrit.extensions.webui.UiCommand;
 | 
			
		||||
import com.google.gerrit.httpd.rpc.Handler;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountDiffPreference;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountPatchReview;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Patch;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.PatchLineComment;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.PatchSet;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Project;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.AccountDiffPreference.Whitespace;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.CurrentUser;
 | 
			
		||||
import com.google.gerrit.server.IdentifiedUser;
 | 
			
		||||
import com.google.gerrit.server.change.ChangeResource;
 | 
			
		||||
import com.google.gerrit.server.change.RevisionResource;
 | 
			
		||||
import com.google.gerrit.server.change.Revisions;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchList;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListCache;
 | 
			
		||||
import com.google.gerrit.server.patch.PatchListKey;
 | 
			
		||||
@@ -44,6 +52,8 @@ import org.eclipse.jgit.lib.ObjectId;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
import java.util.Collections;
 | 
			
		||||
import java.util.Comparator;
 | 
			
		||||
import java.util.HashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
@@ -67,6 +77,7 @@ class PatchSetDetailFactory extends Handler<PatchSetDetail> {
 | 
			
		||||
  private final ReviewDb db;
 | 
			
		||||
  private final PatchListCache patchListCache;
 | 
			
		||||
  private final ChangeControl.Factory changeControlFactory;
 | 
			
		||||
  private final Revisions revisions;
 | 
			
		||||
 | 
			
		||||
  private Project.NameKey projectKey;
 | 
			
		||||
  private final PatchSet.Id psIdBase;
 | 
			
		||||
@@ -83,6 +94,7 @@ class PatchSetDetailFactory extends Handler<PatchSetDetail> {
 | 
			
		||||
  PatchSetDetailFactory(final PatchSetInfoFactory psif, final ReviewDb db,
 | 
			
		||||
      final PatchListCache patchListCache,
 | 
			
		||||
      final ChangeControl.Factory changeControlFactory,
 | 
			
		||||
      final Revisions revisions,
 | 
			
		||||
      @Assisted("psIdBase") @Nullable final PatchSet.Id psIdBase,
 | 
			
		||||
      @Assisted("psIdNew") final PatchSet.Id psIdNew,
 | 
			
		||||
      @Assisted @Nullable final AccountDiffPreference diffPrefs) {
 | 
			
		||||
@@ -90,6 +102,7 @@ class PatchSetDetailFactory extends Handler<PatchSetDetail> {
 | 
			
		||||
    this.db = db;
 | 
			
		||||
    this.patchListCache = patchListCache;
 | 
			
		||||
    this.changeControlFactory = changeControlFactory;
 | 
			
		||||
    this.revisions = revisions;
 | 
			
		||||
 | 
			
		||||
    this.psIdBase = psIdBase;
 | 
			
		||||
    this.psIdNew = psIdNew;
 | 
			
		||||
@@ -164,9 +177,57 @@ class PatchSetDetailFactory extends Handler<PatchSetDetail> {
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RevisionResource rev =
 | 
			
		||||
        new RevisionResource(new ChangeResource(control), patchSet);
 | 
			
		||||
    detail.setCommands(buildCommands(rev));
 | 
			
		||||
    return detail;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private List<UiCommandDetail> buildCommands(RevisionResource rev) {
 | 
			
		||||
    List<UiCommandDetail> all = Lists.newArrayList();
 | 
			
		||||
    for (DynamicMap.Entry<RestView<RevisionResource>> e : revisions.views()) {
 | 
			
		||||
      int d = e.getExportName().indexOf('.');
 | 
			
		||||
      if (d < 0) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      String method = e.getExportName().substring(0, d);
 | 
			
		||||
      String name = e.getExportName().substring(d + 1);
 | 
			
		||||
      RestView<RevisionResource> view;
 | 
			
		||||
      try {
 | 
			
		||||
        view = e.getProvider().get();
 | 
			
		||||
      } catch (RuntimeException err) {
 | 
			
		||||
        log.error(String.format(
 | 
			
		||||
            "error in view %s.%s",
 | 
			
		||||
            e.getPluginName(), e.getExportName()), err);
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
      if (!(view instanceof UiCommand)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      UiCommand<RevisionResource> cmd = (UiCommand<RevisionResource>) view;
 | 
			
		||||
      if (cmd.getPlace() != UiCommand.Place.PATCHSET_ACTION_PANEL
 | 
			
		||||
          || !cmd.isVisible(rev)) {
 | 
			
		||||
        continue;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      UiCommandDetail dsc = new UiCommandDetail();
 | 
			
		||||
      dsc.id = e.getPluginName() + '~' + name;
 | 
			
		||||
      dsc.method = method;
 | 
			
		||||
      dsc.label = cmd.getLabel(rev);
 | 
			
		||||
      dsc.title = cmd.getTitle(rev);
 | 
			
		||||
      dsc.enabled = cmd.isEnabled(rev);
 | 
			
		||||
      all.add(dsc);
 | 
			
		||||
    }
 | 
			
		||||
    Collections.sort(all, new Comparator<UiCommandDetail>() {
 | 
			
		||||
      @Override
 | 
			
		||||
      public int compare(UiCommandDetail a, UiCommandDetail b) {
 | 
			
		||||
        return a.id.compareTo(b.id);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
    return all.isEmpty() ? null : all;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private ObjectId toObjectId(final PatchSet.Id psId) throws OrmException,
 | 
			
		||||
      NoSuchEntityException {
 | 
			
		||||
    final PatchSet ps = db.patchSets().get(psId);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user