Merge changes from topic "mark-reviewed"
* changes: Replace Mute/Unmute by Mark as Reviewed/Unreviewed (Part 3) Replace Mute/Unmute by Mark as Reviewed/Unreviewed (Part 2) Replace Mute/Unmute by Mark as Reviewed/Unreviewed (Part 1)
This commit is contained in:
		@@ -61,18 +61,24 @@ request. They can then decide to remove the ignore star.
 | 
			
		||||
 | 
			
		||||
The ignore star is represented by the special star label 'ignore'.
 | 
			
		||||
 | 
			
		||||
[[mute-star]]
 | 
			
		||||
== Mute Star
 | 
			
		||||
[[reviewed-star]]
 | 
			
		||||
== Reviewed Star
 | 
			
		||||
 | 
			
		||||
If the "mute/<patchset_id>"-star is set by a user, and <patchset_id>
 | 
			
		||||
If the "reviewed/<patchset_id>"-star is set by a user, and <patchset_id>
 | 
			
		||||
matches the current patch set, the change is always reported as "reviewed"
 | 
			
		||||
in the ChangeInfo.
 | 
			
		||||
 | 
			
		||||
This allows users to "de-highlight" changes in a dashboard until a new
 | 
			
		||||
patchset has been uploaded.
 | 
			
		||||
 | 
			
		||||
The ChangeInfo muted-field will show if the change is currently in a
 | 
			
		||||
mute state.
 | 
			
		||||
[[unreviewed-star]]
 | 
			
		||||
== Unreviewed Star
 | 
			
		||||
 | 
			
		||||
If the "unreviewed/<patchset_id>"-star is set by a user, and <patchset_id>
 | 
			
		||||
matches the current patch set, the change is always reported as "unreviewed"
 | 
			
		||||
in the ChangeInfo.
 | 
			
		||||
 | 
			
		||||
This allows users to "highlight" changes in a dashboard.
 | 
			
		||||
 | 
			
		||||
[[query-stars]]
 | 
			
		||||
== Query Stars
 | 
			
		||||
 
 | 
			
		||||
@@ -2329,13 +2329,13 @@ Un-marks a change as ignored.
 | 
			
		||||
  PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/unignore HTTP/1.0
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
[[mute]]
 | 
			
		||||
=== Mute
 | 
			
		||||
[[mark-as-reviewed]]
 | 
			
		||||
=== Mark as Reviewed
 | 
			
		||||
--
 | 
			
		||||
'PUT /changes/link:#change-id[\{change-id\}]/mute'
 | 
			
		||||
'PUT /changes/link:#change-id[\{change-id\}]/reviewed'
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
Marks a change as muted.
 | 
			
		||||
Marks a change as reviewed.
 | 
			
		||||
 | 
			
		||||
This allows users to "de-highlight" changes in their dashboard until a new
 | 
			
		||||
patch set is uploaded.
 | 
			
		||||
@@ -2347,20 +2347,22 @@ link:#unignore[unignored] again.
 | 
			
		||||
 | 
			
		||||
.Request
 | 
			
		||||
----
 | 
			
		||||
  PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/mute HTTP/1.0
 | 
			
		||||
  PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/reviewed HTTP/1.0
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
[[unmute]]
 | 
			
		||||
=== Unmute
 | 
			
		||||
[[mark-as-unreviewed]]
 | 
			
		||||
=== Mark as Unreviewed
 | 
			
		||||
--
 | 
			
		||||
'PUT /changes/link:#change-id[\{change-id\}]/unmute'
 | 
			
		||||
'PUT /changes/link:#change-id[\{change-id\}]/unreviewed'
 | 
			
		||||
--
 | 
			
		||||
 | 
			
		||||
Unmutes a change.
 | 
			
		||||
Marks a change as unreviewed.
 | 
			
		||||
 | 
			
		||||
This allows users to "highlight" changes in their dashboard
 | 
			
		||||
 | 
			
		||||
.Request
 | 
			
		||||
----
 | 
			
		||||
  PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/unmute HTTP/1.0
 | 
			
		||||
  PUT /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/unreviewed HTTP/1.0
 | 
			
		||||
----
 | 
			
		||||
 | 
			
		||||
[[get-hashtags]]
 | 
			
		||||
@@ -5641,8 +5643,6 @@ A list of star labels that are applied by the calling user to this
 | 
			
		||||
change. The labels are lexicographically sorted.
 | 
			
		||||
|`reviewed`           |not set if `false`|
 | 
			
		||||
Whether the change was reviewed by the calling user.
 | 
			
		||||
|`muted`              |not set if `false`|
 | 
			
		||||
Whether the change has been link:#mute[muted] by the calling user.
 | 
			
		||||
Only set if link:#reviewed[reviewed] is requested.
 | 
			
		||||
|`submit_type`        |optional|
 | 
			
		||||
The link:project-configuration.html#submit_type[submit type] of the change. +
 | 
			
		||||
 
 | 
			
		||||
@@ -3374,7 +3374,7 @@ public class ChangeIT extends AbstractDaemonTest {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void mute() throws Exception {
 | 
			
		||||
  public void markAsReviewed() throws Exception {
 | 
			
		||||
    TestAccount user2 = accountCreator.user2();
 | 
			
		||||
 | 
			
		||||
    PushOneCommit.Result r = createChange();
 | 
			
		||||
@@ -3384,16 +3384,16 @@ public class ChangeIT extends AbstractDaemonTest {
 | 
			
		||||
    gApi.changes().id(r.getChangeId()).addReviewer(in);
 | 
			
		||||
 | 
			
		||||
    setApiUser(user);
 | 
			
		||||
    assertThat(gApi.changes().id(r.getChangeId()).muted()).isFalse();
 | 
			
		||||
    gApi.changes().id(r.getChangeId()).mute(true);
 | 
			
		||||
    assertThat(gApi.changes().id(r.getChangeId()).muted()).isTrue();
 | 
			
		||||
    assertThat(gApi.changes().id(r.getChangeId()).get().reviewed).isNull();
 | 
			
		||||
    gApi.changes().id(r.getChangeId()).markAsReviewed(true);
 | 
			
		||||
    assertThat(gApi.changes().id(r.getChangeId()).get().reviewed).isTrue();
 | 
			
		||||
 | 
			
		||||
    setApiUser(user2);
 | 
			
		||||
    sender.clear();
 | 
			
		||||
    amendChange(r.getChangeId());
 | 
			
		||||
 | 
			
		||||
    setApiUser(user);
 | 
			
		||||
    assertThat(gApi.changes().id(r.getChangeId()).muted()).isFalse();
 | 
			
		||||
    assertThat(gApi.changes().id(r.getChangeId()).get().reviewed).isNull();
 | 
			
		||||
 | 
			
		||||
    List<Message> messages = sender.getMessages();
 | 
			
		||||
    assertThat(messages).hasSize(1);
 | 
			
		||||
@@ -3401,12 +3401,73 @@ public class ChangeIT extends AbstractDaemonTest {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void cannotMuteOwnChange() throws Exception {
 | 
			
		||||
  public void cannotSetUnreviewedLabelForPatchSetThatAlreadyHasReviewedLabel() throws Exception {
 | 
			
		||||
    String changeId = createChange().getChangeId();
 | 
			
		||||
 | 
			
		||||
    setApiUser(user);
 | 
			
		||||
    gApi.changes().id(changeId).markAsReviewed(true);
 | 
			
		||||
    assertThat(gApi.changes().id(changeId).get().reviewed).isTrue();
 | 
			
		||||
 | 
			
		||||
    exception.expect(BadRequestException.class);
 | 
			
		||||
    exception.expectMessage("cannot mute own change");
 | 
			
		||||
    gApi.changes().id(changeId).mute(true);
 | 
			
		||||
    exception.expectMessage(
 | 
			
		||||
        "The labels "
 | 
			
		||||
            + StarredChangesUtil.REVIEWED_LABEL
 | 
			
		||||
            + "/"
 | 
			
		||||
            + 1
 | 
			
		||||
            + " and "
 | 
			
		||||
            + StarredChangesUtil.UNREVIEWED_LABEL
 | 
			
		||||
            + "/"
 | 
			
		||||
            + 1
 | 
			
		||||
            + " are mutually exclusive. Only one of them can be set.");
 | 
			
		||||
    gApi.accounts()
 | 
			
		||||
        .self()
 | 
			
		||||
        .setStars(
 | 
			
		||||
            changeId, new StarsInput(ImmutableSet.of(StarredChangesUtil.UNREVIEWED_LABEL + "/1")));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void cannotSetReviewedLabelForPatchSetThatAlreadyHasUnreviewedLabel() throws Exception {
 | 
			
		||||
    String changeId = createChange().getChangeId();
 | 
			
		||||
 | 
			
		||||
    setApiUser(user);
 | 
			
		||||
    gApi.changes().id(changeId).markAsReviewed(false);
 | 
			
		||||
    assertThat(gApi.changes().id(changeId).get().reviewed).isNull();
 | 
			
		||||
 | 
			
		||||
    exception.expect(BadRequestException.class);
 | 
			
		||||
    exception.expectMessage(
 | 
			
		||||
        "The labels "
 | 
			
		||||
            + StarredChangesUtil.REVIEWED_LABEL
 | 
			
		||||
            + "/"
 | 
			
		||||
            + 1
 | 
			
		||||
            + " and "
 | 
			
		||||
            + StarredChangesUtil.UNREVIEWED_LABEL
 | 
			
		||||
            + "/"
 | 
			
		||||
            + 1
 | 
			
		||||
            + " are mutually exclusive. Only one of them can be set.");
 | 
			
		||||
    gApi.accounts()
 | 
			
		||||
        .self()
 | 
			
		||||
        .setStars(
 | 
			
		||||
            changeId, new StarsInput(ImmutableSet.of(StarredChangesUtil.REVIEWED_LABEL + "/1")));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
  public void setReviewedAndUnreviewedLabelsForDifferentPatchSets() throws Exception {
 | 
			
		||||
    String changeId = createChange().getChangeId();
 | 
			
		||||
 | 
			
		||||
    setApiUser(user);
 | 
			
		||||
    gApi.changes().id(changeId).markAsReviewed(true);
 | 
			
		||||
    assertThat(gApi.changes().id(changeId).get().reviewed).isTrue();
 | 
			
		||||
 | 
			
		||||
    amendChange(changeId);
 | 
			
		||||
    assertThat(gApi.changes().id(changeId).get().reviewed).isNull();
 | 
			
		||||
 | 
			
		||||
    gApi.changes().id(changeId).markAsReviewed(false);
 | 
			
		||||
    assertThat(gApi.changes().id(changeId).get().reviewed).isNull();
 | 
			
		||||
 | 
			
		||||
    assertThat(gApi.accounts().self().getStars(changeId))
 | 
			
		||||
        .containsExactly(
 | 
			
		||||
            StarredChangesUtil.REVIEWED_LABEL + "/" + 1,
 | 
			
		||||
            StarredChangesUtil.UNREVIEWED_LABEL + "/" + 2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Test
 | 
			
		||||
 
 | 
			
		||||
@@ -119,18 +119,12 @@ public interface ChangeApi {
 | 
			
		||||
  boolean ignored() throws RestApiException;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Mute or un-mute this change.
 | 
			
		||||
   * Mark this change as reviewed/unreviewed.
 | 
			
		||||
   *
 | 
			
		||||
   * @param mute mute the change if true
 | 
			
		||||
   * @param reviewed flag to decide if this change should be marked as reviewed ({@code true}) or
 | 
			
		||||
   *     unreviewed ({@code false})
 | 
			
		||||
   */
 | 
			
		||||
  void mute(boolean mute) throws RestApiException;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Check if this change is muted.
 | 
			
		||||
   *
 | 
			
		||||
   * @return true if the change is muted.
 | 
			
		||||
   */
 | 
			
		||||
  boolean muted() throws RestApiException;
 | 
			
		||||
  void markAsReviewed(boolean reviewed) throws RestApiException;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Create a new change that reverts this change.
 | 
			
		||||
@@ -583,12 +577,7 @@ public interface ChangeApi {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public void mute(boolean mute) throws RestApiException {
 | 
			
		||||
      throw new NotImplementedException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public boolean muted() throws RestApiException {
 | 
			
		||||
    public void markAsReviewed(boolean reviewed) throws RestApiException {
 | 
			
		||||
      throw new NotImplementedException();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,6 @@ public class ChangeInfo {
 | 
			
		||||
  public Timestamp submitted;
 | 
			
		||||
  public AccountInfo submitter;
 | 
			
		||||
  public Boolean starred;
 | 
			
		||||
  public Boolean muted;
 | 
			
		||||
  public Collection<String> stars;
 | 
			
		||||
  public Boolean reviewed;
 | 
			
		||||
  public SubmitType submitType;
 | 
			
		||||
 
 | 
			
		||||
@@ -138,8 +138,6 @@ public class ChangeInfo extends JavaScriptObject {
 | 
			
		||||
 | 
			
		||||
  public final native boolean starred() /*-{ return this.starred ? true : false; }-*/;
 | 
			
		||||
 | 
			
		||||
  public final native boolean muted() /*-{ return this.muted ? true : false; }-*/;
 | 
			
		||||
 | 
			
		||||
  public final native boolean reviewed() /*-{ return this.reviewed ? true : false; }-*/;
 | 
			
		||||
 | 
			
		||||
  public final native boolean isPrivate() /*-{ return this.is_private ? true : false; }-*/;
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ package com.google.gerrit.server;
 | 
			
		||||
import static com.google.common.base.Preconditions.checkNotNull;
 | 
			
		||||
import static java.nio.charset.StandardCharsets.UTF_8;
 | 
			
		||||
import static java.util.stream.Collectors.joining;
 | 
			
		||||
import static java.util.stream.Collectors.toSet;
 | 
			
		||||
 | 
			
		||||
import com.google.auto.value.AutoValue;
 | 
			
		||||
import com.google.common.base.CharMatcher;
 | 
			
		||||
@@ -26,6 +27,7 @@ import com.google.common.collect.ImmutableListMultimap;
 | 
			
		||||
import com.google.common.collect.ImmutableMap;
 | 
			
		||||
import com.google.common.collect.ImmutableSet;
 | 
			
		||||
import com.google.common.collect.ImmutableSortedSet;
 | 
			
		||||
import com.google.common.collect.Sets;
 | 
			
		||||
import com.google.common.primitives.Ints;
 | 
			
		||||
import com.google.gerrit.common.Nullable;
 | 
			
		||||
import com.google.gerrit.reviewdb.client.Account;
 | 
			
		||||
@@ -49,6 +51,7 @@ import java.io.IOException;
 | 
			
		||||
import java.util.Collection;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Optional;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.SortedSet;
 | 
			
		||||
import java.util.TreeSet;
 | 
			
		||||
@@ -154,7 +157,8 @@ public class StarredChangesUtil {
 | 
			
		||||
 | 
			
		||||
  public static final String DEFAULT_LABEL = "star";
 | 
			
		||||
  public static final String IGNORE_LABEL = "ignore";
 | 
			
		||||
  public static final String MUTE_LABEL = "mute";
 | 
			
		||||
  public static final String REVIEWED_LABEL = "reviewed";
 | 
			
		||||
  public static final String UNREVIEWED_LABEL = "unreviewed";
 | 
			
		||||
  public static final ImmutableSortedSet<String> DEFAULT_LABELS =
 | 
			
		||||
      ImmutableSortedSet.of(DEFAULT_LABEL);
 | 
			
		||||
 | 
			
		||||
@@ -330,37 +334,41 @@ public class StarredChangesUtil {
 | 
			
		||||
    return isIgnoredBy(rsrc.getChange().getId(), rsrc.getUser().asIdentifiedUser().getAccountId());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static String getMuteLabel(Change change) {
 | 
			
		||||
    return MUTE_LABEL + "/" + change.currentPatchSetId().get();
 | 
			
		||||
  private static String getReviewedLabel(Change change) {
 | 
			
		||||
    return getReviewedLabel(change.currentPatchSetId().get());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void mute(ChangeResource rsrc) throws OrmException, IllegalLabelException {
 | 
			
		||||
  private static String getReviewedLabel(int ps) {
 | 
			
		||||
    return REVIEWED_LABEL + "/" + ps;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static String getUnreviewedLabel(Change change) {
 | 
			
		||||
    return getUnreviewedLabel(change.currentPatchSetId().get());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static String getUnreviewedLabel(int ps) {
 | 
			
		||||
    return UNREVIEWED_LABEL + "/" + ps;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void markAsReviewed(ChangeResource rsrc) throws OrmException, IllegalLabelException {
 | 
			
		||||
    star(
 | 
			
		||||
        rsrc.getUser().asIdentifiedUser().getAccountId(),
 | 
			
		||||
        rsrc.getProject(),
 | 
			
		||||
        rsrc.getChange().getId(),
 | 
			
		||||
        ImmutableSet.of(getMuteLabel(rsrc.getChange())),
 | 
			
		||||
        ImmutableSet.of());
 | 
			
		||||
        ImmutableSet.of(getReviewedLabel(rsrc.getChange())),
 | 
			
		||||
        ImmutableSet.of(getUnreviewedLabel(rsrc.getChange())));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void unmute(ChangeResource rsrc) throws OrmException, IllegalLabelException {
 | 
			
		||||
  public void markAsUnreviewed(ChangeResource rsrc) throws OrmException, IllegalLabelException {
 | 
			
		||||
    star(
 | 
			
		||||
        rsrc.getUser().asIdentifiedUser().getAccountId(),
 | 
			
		||||
        rsrc.getProject(),
 | 
			
		||||
        rsrc.getChange().getId(),
 | 
			
		||||
        ImmutableSet.of(),
 | 
			
		||||
        ImmutableSet.of(getMuteLabel(rsrc.getChange())));
 | 
			
		||||
        ImmutableSet.of(getUnreviewedLabel(rsrc.getChange())),
 | 
			
		||||
        ImmutableSet.of(getReviewedLabel(rsrc.getChange())));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isMutedBy(Change change, Account.Id accountId) throws OrmException {
 | 
			
		||||
    return getLabels(accountId, change.getId()).contains(getMuteLabel(change));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isMuted(ChangeResource rsrc) throws OrmException {
 | 
			
		||||
    return isMutedBy(rsrc.getChange(), rsrc.getUser().asIdentifiedUser().getAccountId());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static StarRef readLabels(Repository repo, String refName) throws IOException {
 | 
			
		||||
  public static StarRef readLabels(Repository repo, String refName) throws IOException {
 | 
			
		||||
    Ref ref = repo.exactRef(refName);
 | 
			
		||||
    if (ref == null) {
 | 
			
		||||
      return StarRef.MISSING;
 | 
			
		||||
@@ -394,6 +402,25 @@ public class StarredChangesUtil {
 | 
			
		||||
    if (labels.containsAll(ImmutableSet.of(DEFAULT_LABEL, IGNORE_LABEL))) {
 | 
			
		||||
      throw new MutuallyExclusiveLabelsException(DEFAULT_LABEL, IGNORE_LABEL);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Set<Integer> reviewedPatchSets =
 | 
			
		||||
        labels
 | 
			
		||||
            .stream()
 | 
			
		||||
            .filter(l -> l.startsWith(REVIEWED_LABEL))
 | 
			
		||||
            .map(l -> Integer.valueOf(l.substring(REVIEWED_LABEL.length() + 1)))
 | 
			
		||||
            .collect(toSet());
 | 
			
		||||
    Set<Integer> unreviewedPatchSets =
 | 
			
		||||
        labels
 | 
			
		||||
            .stream()
 | 
			
		||||
            .filter(l -> l.startsWith(UNREVIEWED_LABEL))
 | 
			
		||||
            .map(l -> Integer.valueOf(l.substring(UNREVIEWED_LABEL.length() + 1)))
 | 
			
		||||
            .collect(toSet());
 | 
			
		||||
    Optional<Integer> ps =
 | 
			
		||||
        Sets.intersection(reviewedPatchSets, unreviewedPatchSets).stream().findFirst();
 | 
			
		||||
    if (ps.isPresent()) {
 | 
			
		||||
      throw new MutuallyExclusiveLabelsException(
 | 
			
		||||
          getReviewedLabel(ps.get()), getUnreviewedLabel(ps.get()));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private static void validateLabels(Collection<String> labels) throws InvalidLabelsException {
 | 
			
		||||
 
 | 
			
		||||
@@ -69,8 +69,9 @@ import com.google.gerrit.server.change.Index;
 | 
			
		||||
import com.google.gerrit.server.change.ListChangeComments;
 | 
			
		||||
import com.google.gerrit.server.change.ListChangeDrafts;
 | 
			
		||||
import com.google.gerrit.server.change.ListChangeRobotComments;
 | 
			
		||||
import com.google.gerrit.server.change.MarkAsReviewed;
 | 
			
		||||
import com.google.gerrit.server.change.MarkAsUnreviewed;
 | 
			
		||||
import com.google.gerrit.server.change.Move;
 | 
			
		||||
import com.google.gerrit.server.change.Mute;
 | 
			
		||||
import com.google.gerrit.server.change.PostHashtags;
 | 
			
		||||
import com.google.gerrit.server.change.PostPrivate;
 | 
			
		||||
import com.google.gerrit.server.change.PostReviewers;
 | 
			
		||||
@@ -88,7 +89,6 @@ import com.google.gerrit.server.change.SetWorkInProgress;
 | 
			
		||||
import com.google.gerrit.server.change.SubmittedTogether;
 | 
			
		||||
import com.google.gerrit.server.change.SuggestChangeReviewers;
 | 
			
		||||
import com.google.gerrit.server.change.Unignore;
 | 
			
		||||
import com.google.gerrit.server.change.Unmute;
 | 
			
		||||
import com.google.gerrit.server.change.WorkInProgressOp;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
@@ -140,8 +140,8 @@ class ChangeApiImpl implements ChangeApi {
 | 
			
		||||
  private final DeletePrivate deletePrivate;
 | 
			
		||||
  private final Ignore ignore;
 | 
			
		||||
  private final Unignore unignore;
 | 
			
		||||
  private final Mute mute;
 | 
			
		||||
  private final Unmute unmute;
 | 
			
		||||
  private final MarkAsReviewed markAsReviewed;
 | 
			
		||||
  private final MarkAsUnreviewed markAsUnreviewed;
 | 
			
		||||
  private final SetWorkInProgress setWip;
 | 
			
		||||
  private final SetReadyForReview setReady;
 | 
			
		||||
  private final PutMessage putMessage;
 | 
			
		||||
@@ -185,8 +185,8 @@ class ChangeApiImpl implements ChangeApi {
 | 
			
		||||
      DeletePrivate deletePrivate,
 | 
			
		||||
      Ignore ignore,
 | 
			
		||||
      Unignore unignore,
 | 
			
		||||
      Mute mute,
 | 
			
		||||
      Unmute unmute,
 | 
			
		||||
      MarkAsReviewed markAsReviewed,
 | 
			
		||||
      MarkAsUnreviewed markAsUnreviewed,
 | 
			
		||||
      SetWorkInProgress setWip,
 | 
			
		||||
      SetReadyForReview setReady,
 | 
			
		||||
      PutMessage putMessage,
 | 
			
		||||
@@ -228,8 +228,8 @@ class ChangeApiImpl implements ChangeApi {
 | 
			
		||||
    this.deletePrivate = deletePrivate;
 | 
			
		||||
    this.ignore = ignore;
 | 
			
		||||
    this.unignore = unignore;
 | 
			
		||||
    this.mute = mute;
 | 
			
		||||
    this.unmute = unmute;
 | 
			
		||||
    this.markAsReviewed = markAsReviewed;
 | 
			
		||||
    this.markAsUnreviewed = markAsUnreviewed;
 | 
			
		||||
    this.setWip = setWip;
 | 
			
		||||
    this.setReady = setReady;
 | 
			
		||||
    this.putMessage = putMessage;
 | 
			
		||||
@@ -677,26 +677,18 @@ class ChangeApiImpl implements ChangeApi {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void mute(boolean mute) throws RestApiException {
 | 
			
		||||
  public void markAsReviewed(boolean reviewed) throws RestApiException {
 | 
			
		||||
    // TODO(dborowitz): Convert to RetryingRestModifyView. Needs to plumb BatchUpdate.Factory into
 | 
			
		||||
    // StarredChangesUtil.
 | 
			
		||||
    try {
 | 
			
		||||
      if (mute) {
 | 
			
		||||
        this.mute.apply(change, new Mute.Input());
 | 
			
		||||
      if (reviewed) {
 | 
			
		||||
        markAsReviewed.apply(change, new MarkAsReviewed.Input());
 | 
			
		||||
      } else {
 | 
			
		||||
        unmute.apply(change, new Unmute.Input());
 | 
			
		||||
        markAsUnreviewed.apply(change, new MarkAsUnreviewed.Input());
 | 
			
		||||
      }
 | 
			
		||||
    } catch (OrmException | IllegalLabelException e) {
 | 
			
		||||
      throw asRestApiException("Cannot mute change", e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public boolean muted() throws RestApiException {
 | 
			
		||||
    try {
 | 
			
		||||
      return stars.isMuted(change);
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      throw asRestApiException("Cannot check if muted", e);
 | 
			
		||||
      throw asRestApiException(
 | 
			
		||||
          "Cannot mark change as " + (reviewed ? "reviewed" : "unreviewed"), e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -551,22 +551,13 @@ public class ChangeJson {
 | 
			
		||||
    if (user.isIdentifiedUser()) {
 | 
			
		||||
      Collection<String> stars = cd.stars(user.getAccountId());
 | 
			
		||||
      out.starred = stars.contains(StarredChangesUtil.DEFAULT_LABEL) ? true : null;
 | 
			
		||||
      out.muted =
 | 
			
		||||
          stars.contains(StarredChangesUtil.MUTE_LABEL + "/" + cd.currentPatchSet().getPatchSetId())
 | 
			
		||||
              ? true
 | 
			
		||||
              : null;
 | 
			
		||||
      if (!stars.isEmpty()) {
 | 
			
		||||
        out.stars = stars;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (in.getStatus().isOpen() && has(REVIEWED) && user.isIdentifiedUser()) {
 | 
			
		||||
      Account.Id accountId = user.getAccountId();
 | 
			
		||||
      if (out.muted != null) {
 | 
			
		||||
        out.reviewed = true;
 | 
			
		||||
      } else {
 | 
			
		||||
        out.reviewed = cd.reviewedBy().contains(accountId) ? true : null;
 | 
			
		||||
      }
 | 
			
		||||
      out.reviewed = cd.isReviewedBy(user.getAccountId()) ? true : null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    out.labels = labelsFor(perm, cd, has(LABELS), has(DETAILED_LABELS));
 | 
			
		||||
 
 | 
			
		||||
@@ -14,66 +14,64 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.server.change;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.extensions.restapi.BadRequestException;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.Response;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestApiException;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestModifyView;
 | 
			
		||||
import com.google.gerrit.extensions.webui.UiAction;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil.IllegalLabelException;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeData;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
@Singleton
 | 
			
		||||
public class Mute implements RestModifyView<ChangeResource, Mute.Input>, UiAction<ChangeResource> {
 | 
			
		||||
  private static final Logger log = LoggerFactory.getLogger(Mute.class);
 | 
			
		||||
public class MarkAsReviewed
 | 
			
		||||
    implements RestModifyView<ChangeResource, MarkAsReviewed.Input>, UiAction<ChangeResource> {
 | 
			
		||||
  private static final Logger log = LoggerFactory.getLogger(MarkAsReviewed.class);
 | 
			
		||||
 | 
			
		||||
  public static class Input {}
 | 
			
		||||
 | 
			
		||||
  private final Provider<ReviewDb> dbProvider;
 | 
			
		||||
  private final ChangeData.Factory changeDataFactory;
 | 
			
		||||
  private final StarredChangesUtil stars;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  Mute(StarredChangesUtil stars) {
 | 
			
		||||
  MarkAsReviewed(
 | 
			
		||||
      Provider<ReviewDb> dbProvider,
 | 
			
		||||
      ChangeData.Factory changeDataFactory,
 | 
			
		||||
      StarredChangesUtil stars) {
 | 
			
		||||
    this.dbProvider = dbProvider;
 | 
			
		||||
    this.changeDataFactory = changeDataFactory;
 | 
			
		||||
    this.stars = stars;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Description getDescription(ChangeResource rsrc) {
 | 
			
		||||
    return new UiAction.Description()
 | 
			
		||||
        .setLabel("Mute")
 | 
			
		||||
        .setTitle("Mute the change to unhighlight it in the dashboard")
 | 
			
		||||
        .setVisible(isMuteable(rsrc));
 | 
			
		||||
        .setLabel("Mark Reviewed")
 | 
			
		||||
        .setTitle("Mark the change as reviewed to unhighlight it in the dashboard")
 | 
			
		||||
        .setVisible(!isReviewed(rsrc));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Response<String> apply(ChangeResource rsrc, Input input)
 | 
			
		||||
      throws RestApiException, OrmException, IllegalLabelException {
 | 
			
		||||
    if (rsrc.isUserOwner()) {
 | 
			
		||||
      throw new BadRequestException("cannot mute own change");
 | 
			
		||||
    }
 | 
			
		||||
    if (!isMuted(rsrc)) {
 | 
			
		||||
      stars.mute(rsrc);
 | 
			
		||||
    }
 | 
			
		||||
    stars.markAsReviewed(rsrc);
 | 
			
		||||
    return Response.ok("");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private boolean isMuted(ChangeResource rsrc) {
 | 
			
		||||
  private boolean isReviewed(ChangeResource rsrc) {
 | 
			
		||||
    try {
 | 
			
		||||
      return stars.isMuted(rsrc);
 | 
			
		||||
      return changeDataFactory
 | 
			
		||||
          .create(dbProvider.get(), rsrc.getNotes())
 | 
			
		||||
          .isReviewedBy(rsrc.getUser().asIdentifiedUser().getAccountId());
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      log.error("failed to check muted star", e);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private boolean isMuteable(ChangeResource rsrc) {
 | 
			
		||||
    try {
 | 
			
		||||
      return !rsrc.isUserOwner() && !isMuted(rsrc) && !stars.isIgnored(rsrc);
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      log.error("failed to check ignored star", e);
 | 
			
		||||
      log.error("failed to check if change is reviewed", e);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
@@ -17,50 +17,60 @@ package com.google.gerrit.server.change;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.Response;
 | 
			
		||||
import com.google.gerrit.extensions.restapi.RestModifyView;
 | 
			
		||||
import com.google.gerrit.extensions.webui.UiAction;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil.IllegalLabelException;
 | 
			
		||||
import com.google.gerrit.server.query.change.ChangeData;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import com.google.inject.Singleton;
 | 
			
		||||
import org.slf4j.Logger;
 | 
			
		||||
import org.slf4j.LoggerFactory;
 | 
			
		||||
 | 
			
		||||
@Singleton
 | 
			
		||||
public class Unmute
 | 
			
		||||
    implements RestModifyView<ChangeResource, Unmute.Input>, UiAction<ChangeResource> {
 | 
			
		||||
  private static final Logger log = LoggerFactory.getLogger(Unmute.class);
 | 
			
		||||
public class MarkAsUnreviewed
 | 
			
		||||
    implements RestModifyView<ChangeResource, MarkAsUnreviewed.Input>, UiAction<ChangeResource> {
 | 
			
		||||
  private static final Logger log = LoggerFactory.getLogger(MarkAsUnreviewed.class);
 | 
			
		||||
 | 
			
		||||
  public static class Input {}
 | 
			
		||||
 | 
			
		||||
  private final Provider<ReviewDb> dbProvider;
 | 
			
		||||
  private final ChangeData.Factory changeDataFactory;
 | 
			
		||||
  private final StarredChangesUtil stars;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  Unmute(StarredChangesUtil stars) {
 | 
			
		||||
  MarkAsUnreviewed(
 | 
			
		||||
      Provider<ReviewDb> dbProvider,
 | 
			
		||||
      ChangeData.Factory changeDataFactory,
 | 
			
		||||
      StarredChangesUtil stars) {
 | 
			
		||||
    this.dbProvider = dbProvider;
 | 
			
		||||
    this.changeDataFactory = changeDataFactory;
 | 
			
		||||
    this.stars = stars;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Description getDescription(ChangeResource rsrc) {
 | 
			
		||||
    return new UiAction.Description()
 | 
			
		||||
        .setLabel("Unmute")
 | 
			
		||||
        .setTitle("Unmute the change")
 | 
			
		||||
        .setVisible(isMuted(rsrc));
 | 
			
		||||
        .setLabel("Mark Unreviewed")
 | 
			
		||||
        .setTitle("Mark the change as unreviewed to highlight it in the dashboard")
 | 
			
		||||
        .setVisible(isReviewed(rsrc));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public Response<String> apply(ChangeResource rsrc, Input input)
 | 
			
		||||
      throws OrmException, IllegalLabelException {
 | 
			
		||||
    if (isMuted(rsrc)) {
 | 
			
		||||
      stars.unmute(rsrc);
 | 
			
		||||
    }
 | 
			
		||||
    stars.markAsUnreviewed(rsrc);
 | 
			
		||||
    return Response.ok("");
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private boolean isMuted(ChangeResource rsrc) {
 | 
			
		||||
  private boolean isReviewed(ChangeResource rsrc) {
 | 
			
		||||
    try {
 | 
			
		||||
      return stars.isMuted(rsrc);
 | 
			
		||||
      return changeDataFactory
 | 
			
		||||
          .create(dbProvider.get(), rsrc.getNotes())
 | 
			
		||||
          .isReviewedBy(rsrc.getUser().asIdentifiedUser().getAccountId());
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      log.error("failed to check muted star", e);
 | 
			
		||||
      log.error("failed to check if change is reviewed", e);
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
@@ -90,8 +90,8 @@ public class Module extends RestApiModule {
 | 
			
		||||
    delete(CHANGE_KIND, "private").to(DeletePrivate.class);
 | 
			
		||||
    put(CHANGE_KIND, "ignore").to(Ignore.class);
 | 
			
		||||
    put(CHANGE_KIND, "unignore").to(Unignore.class);
 | 
			
		||||
    put(CHANGE_KIND, "mute").to(Mute.class);
 | 
			
		||||
    put(CHANGE_KIND, "unmute").to(Unmute.class);
 | 
			
		||||
    put(CHANGE_KIND, "reviewed").to(MarkAsReviewed.class);
 | 
			
		||||
    put(CHANGE_KIND, "unreviewed").to(MarkAsUnreviewed.class);
 | 
			
		||||
    post(CHANGE_KIND, "wip").to(SetWorkInProgress.class);
 | 
			
		||||
    post(CHANGE_KIND, "ready").to(SetReadyForReview.class);
 | 
			
		||||
    put(CHANGE_KIND, "message").to(PutMessage.class);
 | 
			
		||||
 
 | 
			
		||||
@@ -91,7 +91,10 @@ public class ChangeSchemaDefinitions extends SchemaDefinitions<ChangeData> {
 | 
			
		||||
  @Deprecated static final Schema<ChangeData> V46 = schema(V45);
 | 
			
		||||
 | 
			
		||||
  // Removal of draft change workflow requires reindexing
 | 
			
		||||
  static final Schema<ChangeData> V47 = schema(V46);
 | 
			
		||||
  @Deprecated static final Schema<ChangeData> V47 = schema(V46);
 | 
			
		||||
 | 
			
		||||
  // Rename of star label 'mute' to 'reviewed' requires reindexing
 | 
			
		||||
  static final Schema<ChangeData> V48 = schema(V47);
 | 
			
		||||
 | 
			
		||||
  public static final String NAME = "changes";
 | 
			
		||||
  public static final ChangeSchemaDefinitions INSTANCE = new ChangeSchemaDefinitions();
 | 
			
		||||
 
 | 
			
		||||
@@ -1084,6 +1084,22 @@ public class ChangeData {
 | 
			
		||||
    return draftsByUser;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public boolean isReviewedBy(Account.Id accountId) throws OrmException {
 | 
			
		||||
    Collection<String> stars = stars(accountId);
 | 
			
		||||
 | 
			
		||||
    if (stars.contains(
 | 
			
		||||
        StarredChangesUtil.REVIEWED_LABEL + "/" + currentPatchSet().getPatchSetId())) {
 | 
			
		||||
      return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (stars.contains(
 | 
			
		||||
        StarredChangesUtil.UNREVIEWED_LABEL + "/" + currentPatchSet().getPatchSetId())) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return reviewedBy().contains(accountId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public Set<Account.Id> reviewedBy() throws OrmException {
 | 
			
		||||
    if (reviewedBy == null) {
 | 
			
		||||
      if (!lazyLoad) {
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ import java.util.concurrent.TimeUnit;
 | 
			
		||||
/** A version of the database schema. */
 | 
			
		||||
public abstract class SchemaVersion {
 | 
			
		||||
  /** The current schema version. */
 | 
			
		||||
  public static final Class<Schema_160> C = Schema_160.class;
 | 
			
		||||
  public static final Class<Schema_161> C = Schema_161.class;
 | 
			
		||||
 | 
			
		||||
  public static int getBinaryVersion() {
 | 
			
		||||
    return guessVersion(C);
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,76 @@
 | 
			
		||||
// Copyright (C) 2017 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.server.schema;
 | 
			
		||||
 | 
			
		||||
import static java.util.stream.Collectors.toList;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.reviewdb.client.RefNames;
 | 
			
		||||
import com.google.gerrit.reviewdb.server.ReviewDb;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil.IllegalLabelException;
 | 
			
		||||
import com.google.gerrit.server.StarredChangesUtil.StarRef;
 | 
			
		||||
import com.google.gerrit.server.config.AllUsersName;
 | 
			
		||||
import com.google.gerrit.server.git.GitRepositoryManager;
 | 
			
		||||
import com.google.gwtorm.server.OrmException;
 | 
			
		||||
import com.google.inject.Inject;
 | 
			
		||||
import com.google.inject.Provider;
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import org.eclipse.jgit.lib.BatchRefUpdate;
 | 
			
		||||
import org.eclipse.jgit.lib.ObjectId;
 | 
			
		||||
import org.eclipse.jgit.lib.Ref;
 | 
			
		||||
import org.eclipse.jgit.lib.Repository;
 | 
			
		||||
import org.eclipse.jgit.lib.TextProgressMonitor;
 | 
			
		||||
import org.eclipse.jgit.revwalk.RevWalk;
 | 
			
		||||
import org.eclipse.jgit.transport.ReceiveCommand;
 | 
			
		||||
 | 
			
		||||
public class Schema_161 extends SchemaVersion {
 | 
			
		||||
  private static final String MUTE_LABEL = "mute";
 | 
			
		||||
 | 
			
		||||
  private final GitRepositoryManager repoManager;
 | 
			
		||||
  private final AllUsersName allUsersName;
 | 
			
		||||
 | 
			
		||||
  @Inject
 | 
			
		||||
  Schema_161(
 | 
			
		||||
      Provider<Schema_160> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
 | 
			
		||||
    super(prior);
 | 
			
		||||
    this.repoManager = repoManager;
 | 
			
		||||
    this.allUsersName = allUsersName;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
 | 
			
		||||
    try (Repository git = repoManager.openRepository(allUsersName);
 | 
			
		||||
        RevWalk rw = new RevWalk(git)) {
 | 
			
		||||
      BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
 | 
			
		||||
      for (Ref ref : git.getRefDatabase().getRefs(RefNames.REFS_STARRED_CHANGES).values()) {
 | 
			
		||||
        StarRef starRef = StarredChangesUtil.readLabels(git, ref.getName());
 | 
			
		||||
        if (starRef.labels().contains(MUTE_LABEL)) {
 | 
			
		||||
          ObjectId id =
 | 
			
		||||
              StarredChangesUtil.writeLabels(
 | 
			
		||||
                  git,
 | 
			
		||||
                  starRef
 | 
			
		||||
                      .labels()
 | 
			
		||||
                      .stream()
 | 
			
		||||
                      .map(l -> l.equals(MUTE_LABEL) ? StarredChangesUtil.REVIEWED_LABEL : l)
 | 
			
		||||
                      .collect(toList()));
 | 
			
		||||
          bru.addCommand(new ReceiveCommand(ObjectId.zeroId(), id, ref.getName()));
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      bru.execute(rw, new TextProgressMonitor());
 | 
			
		||||
    } catch (IOException | IllegalLabelException ex) {
 | 
			
		||||
      throw new OrmException(ex);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -54,15 +54,15 @@
 | 
			
		||||
    DELETE_EDIT: 'deleteEdit',
 | 
			
		||||
    IGNORE: 'ignore',
 | 
			
		||||
    MOVE: 'move',
 | 
			
		||||
    MUTE: 'mute',
 | 
			
		||||
    PRIVATE: 'private',
 | 
			
		||||
    PRIVATE_DELETE: 'private.delete',
 | 
			
		||||
    PUBLISH_EDIT: 'publishEdit',
 | 
			
		||||
    REBASE_EDIT: 'rebaseEdit',
 | 
			
		||||
    RESTORE: 'restore',
 | 
			
		||||
    REVERT: 'revert',
 | 
			
		||||
    REVIEWED: 'reviewed',
 | 
			
		||||
    UNIGNORE: 'unignore',
 | 
			
		||||
    UNMUTE: 'unmute',
 | 
			
		||||
    UNREVIEWED: 'unreviewed',
 | 
			
		||||
    WIP: 'wip',
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@@ -267,11 +267,11 @@
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: ActionType.CHANGE,
 | 
			
		||||
              key: ChangeActions.MUTE,
 | 
			
		||||
              key: ChangeActions.REVIEWED,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: ActionType.CHANGE,
 | 
			
		||||
              key: ChangeActions.UNMUTE,
 | 
			
		||||
              key: ChangeActions.UNREVIEWED,
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
              type: ActionType.CHANGE,
 | 
			
		||||
 
 | 
			
		||||
@@ -866,22 +866,22 @@ limitations under the License.
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    suite('mute change', () => {
 | 
			
		||||
    suite('reviewed change', () => {
 | 
			
		||||
      setup(done => {
 | 
			
		||||
        sandbox.stub(element, '_fireAction');
 | 
			
		||||
 | 
			
		||||
        const MuteAction = {
 | 
			
		||||
          __key: 'mute',
 | 
			
		||||
        const ReviewedAction = {
 | 
			
		||||
          __key: 'reviewed',
 | 
			
		||||
          __type: 'change',
 | 
			
		||||
          __primary: false,
 | 
			
		||||
          method: 'PUT',
 | 
			
		||||
          label: 'Mute',
 | 
			
		||||
          label: 'Mark reviewed',
 | 
			
		||||
          title: 'Working...',
 | 
			
		||||
          enabled: true,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        element.actions = {
 | 
			
		||||
          mute: MuteAction,
 | 
			
		||||
          reviewed: ReviewedAction,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        element.changeNum = '2';
 | 
			
		||||
@@ -890,37 +890,38 @@ limitations under the License.
 | 
			
		||||
        element.reload().then(() => { flush(done); });
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      test('make sure the mute button is not outside of the overflow menu',
 | 
			
		||||
      test('make sure the reviewed button is not outside of the overflow menu',
 | 
			
		||||
          () => {
 | 
			
		||||
            assert.isNotOk(element.$$('[data-action-key="mute"]'));
 | 
			
		||||
            assert.isNotOk(element.$$('[data-action-key="reviewed"]'));
 | 
			
		||||
          });
 | 
			
		||||
 | 
			
		||||
      test('muting change', () => {
 | 
			
		||||
        assert.isOk(element.$.moreActions.$$('span[data-id="mute-change"]'));
 | 
			
		||||
        element.setActionOverflow('change', 'mute', false);
 | 
			
		||||
      test('reviewing change', () => {
 | 
			
		||||
        assert.isOk(
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="reviewed-change"]'));
 | 
			
		||||
        element.setActionOverflow('change', 'reviewed', false);
 | 
			
		||||
        flushAsynchronousOperations();
 | 
			
		||||
        assert.isOk(element.$$('[data-action-key="mute"]'));
 | 
			
		||||
        assert.isOk(element.$$('[data-action-key="reviewed"]'));
 | 
			
		||||
        assert.isNotOk(
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="mute-change"]'));
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="reviewed-change"]'));
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    suite('unmute change', () => {
 | 
			
		||||
    suite('unreviewed change', () => {
 | 
			
		||||
      setup(done => {
 | 
			
		||||
        sandbox.stub(element, '_fireAction');
 | 
			
		||||
 | 
			
		||||
        const UnmuteAction = {
 | 
			
		||||
          __key: 'unmute',
 | 
			
		||||
        const UnreviewedAction = {
 | 
			
		||||
          __key: 'unreviewed',
 | 
			
		||||
          __type: 'change',
 | 
			
		||||
          __primary: false,
 | 
			
		||||
          method: 'PUT',
 | 
			
		||||
          label: 'Unmute',
 | 
			
		||||
          label: 'Mark unreviewed',
 | 
			
		||||
          title: 'Working...',
 | 
			
		||||
          enabled: true,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        element.actions = {
 | 
			
		||||
          unmute: UnmuteAction,
 | 
			
		||||
          unreviewed: UnreviewedAction,
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        element.changeNum = '2';
 | 
			
		||||
@@ -930,18 +931,18 @@ limitations under the License.
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
      test('unmute button not outside of the overflow menu', () => {
 | 
			
		||||
        assert.isNotOk(element.$$('[data-action-key="unmute"]'));
 | 
			
		||||
      test('unreviewed button not outside of the overflow menu', () => {
 | 
			
		||||
        assert.isNotOk(element.$$('[data-action-key="unreviewed"]'));
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      test('unmuting change', () => {
 | 
			
		||||
      test('unreviewed change', () => {
 | 
			
		||||
        assert.isOk(
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="unmute-change"]'));
 | 
			
		||||
        element.setActionOverflow('change', 'unmute', false);
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="unreviewed-change"]'));
 | 
			
		||||
        element.setActionOverflow('change', 'unreviewed', false);
 | 
			
		||||
        flushAsynchronousOperations();
 | 
			
		||||
        assert.isOk(element.$$('[data-action-key="unmute"]'));
 | 
			
		||||
        assert.isOk(element.$$('[data-action-key="unreviewed"]'));
 | 
			
		||||
        assert.isNotOk(
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="unmute-change"]'));
 | 
			
		||||
            element.$.moreActions.$$('span[data-id="unreviewed-change"]'));
 | 
			
		||||
      });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user