Implement starred changes for user accounts, including async toggling
Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
		@@ -15,10 +15,30 @@
 | 
			
		||||
package com.google.gerrit.client.changes;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.client.data.AccountDashboardInfo;
 | 
			
		||||
import com.google.gerrit.client.data.ChangeInfo;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Account;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Change;
 | 
			
		||||
import com.google.gwt.user.client.rpc.AsyncCallback;
 | 
			
		||||
import com.google.gwtjsonrpc.client.RemoteJsonService;
 | 
			
		||||
import com.google.gwtjsonrpc.client.VoidResult;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public interface ChangeListService extends RemoteJsonService {
 | 
			
		||||
  /** Get the data to show {@link AccountDashboardScreen} for an account. */
 | 
			
		||||
  void forAccount(Account.Id id, AsyncCallback<AccountDashboardInfo> callback);
 | 
			
		||||
 | 
			
		||||
  /** Get the changes starred by the caller. */
 | 
			
		||||
  void myStarredChanges(AsyncCallback<List<ChangeInfo>> callback);
 | 
			
		||||
 | 
			
		||||
  /** Get the ids of all changes starred by the caller. */
 | 
			
		||||
  void myStarredChangeIds(AsyncCallback<Set<Change.Id>> callback);
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Add and/or remove changes from the set of starred changes of the caller.
 | 
			
		||||
   * 
 | 
			
		||||
   * @param req the add and remove cluster.
 | 
			
		||||
   */
 | 
			
		||||
  void toggleStars(ToggleStarRequest req, AsyncCallback<VoidResult> callback);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,14 +9,20 @@ import com.google.gerrit.client.reviewdb.Account;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Change;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.ChangeAccess;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.ReviewDb;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.StarredChange;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Change.Id;
 | 
			
		||||
import com.google.gwt.user.client.rpc.AsyncCallback;
 | 
			
		||||
import com.google.gwtjsonrpc.client.CookieAccess;
 | 
			
		||||
import com.google.gwtjsonrpc.client.VoidResult;
 | 
			
		||||
import com.google.gwtorm.client.OrmException;
 | 
			
		||||
import com.google.gwtorm.client.ResultSet;
 | 
			
		||||
import com.google.gwtorm.client.SchemaFactory;
 | 
			
		||||
import com.google.gwtorm.client.Transaction;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
public class ChangeListServiceImpl implements ChangeListService {
 | 
			
		||||
  private final SchemaFactory<ReviewDb> schema;
 | 
			
		||||
@@ -27,8 +33,9 @@ public class ChangeListServiceImpl implements ChangeListService {
 | 
			
		||||
 | 
			
		||||
  public void forAccount(Account.Id id,
 | 
			
		||||
      AsyncCallback<AccountDashboardInfo> callback) {
 | 
			
		||||
    final Account.Id me = idFromCookie();
 | 
			
		||||
    if (id == null) {
 | 
			
		||||
      id = idFromCookie();
 | 
			
		||||
      id = me;
 | 
			
		||||
    }
 | 
			
		||||
    if (id == null) {
 | 
			
		||||
      callback.onFailure(new IllegalArgumentException("No Account.Id"));
 | 
			
		||||
@@ -45,12 +52,19 @@ public class ChangeListServiceImpl implements ChangeListService {
 | 
			
		||||
          return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final Set<Change.Id> starred = new HashSet<Change.Id>();
 | 
			
		||||
        if (me != null) {
 | 
			
		||||
          for (final StarredChange sc : db.starredChanges().byAccount(me)) {
 | 
			
		||||
            starred.add(sc.getChangeId());
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final ChangeAccess changes = db.changes();
 | 
			
		||||
        final AccountDashboardInfo d;
 | 
			
		||||
 | 
			
		||||
        d = new AccountDashboardInfo(new AccountInfo(user));
 | 
			
		||||
        d.setByOwner(toInfoList(changes.byOwnerOpen(user.getId()), accts));
 | 
			
		||||
        d.setClosed(toInfoList(changes.byOwnerMerged(user.getId()), accts));
 | 
			
		||||
        d.setByOwner(list(changes.byOwnerOpen(user.getId()), starred, accts));
 | 
			
		||||
        d.setClosed(list(changes.byOwnerMerged(user.getId()), starred, accts));
 | 
			
		||||
        callback.onSuccess(d);
 | 
			
		||||
      } finally {
 | 
			
		||||
        db.close();
 | 
			
		||||
@@ -60,11 +74,108 @@ public class ChangeListServiceImpl implements ChangeListService {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private List<ChangeInfo> toInfoList(final ResultSet<Change> rs,
 | 
			
		||||
      final AccountCache accts) throws OrmException {
 | 
			
		||||
  public void myStarredChanges(final AsyncCallback<List<ChangeInfo>> callback) {
 | 
			
		||||
    final Account.Id me = idFromCookie();
 | 
			
		||||
    if (me == null) {
 | 
			
		||||
      callback.onFailure(new IllegalArgumentException("Not signed in"));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    try {
 | 
			
		||||
      final ReviewDb db = schema.open();
 | 
			
		||||
      try {
 | 
			
		||||
        final AccountCache accts = new AccountCache(db);
 | 
			
		||||
        final Set<Change.Id> starred = new HashSet<Change.Id>();
 | 
			
		||||
        for (final StarredChange sc : db.starredChanges().byAccount(me)) {
 | 
			
		||||
          starred.add(sc.getChangeId());
 | 
			
		||||
        }
 | 
			
		||||
        callback.onSuccess(list(db.changes().get(starred), starred, accts));
 | 
			
		||||
      } finally {
 | 
			
		||||
        db.close();
 | 
			
		||||
      }
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      callback.onFailure(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void toggleStars(final ToggleStarRequest req,
 | 
			
		||||
      final AsyncCallback<VoidResult> callback) {
 | 
			
		||||
    final Account.Id me = idFromCookie();
 | 
			
		||||
    if (me == null) {
 | 
			
		||||
      callback.onFailure(new IllegalArgumentException("Not signed in"));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      final ReviewDb db = schema.open();
 | 
			
		||||
      try {
 | 
			
		||||
        final Set<Change.Id> existing = new HashSet<Change.Id>();
 | 
			
		||||
        for (final StarredChange sc : db.starredChanges().byAccount(me)) {
 | 
			
		||||
          existing.add(sc.getChangeId());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        final ArrayList<StarredChange> add = new ArrayList<StarredChange>();
 | 
			
		||||
        final ArrayList<StarredChange> remove = new ArrayList<StarredChange>();
 | 
			
		||||
        if (req.getAddSet() != null) {
 | 
			
		||||
          for (final Change.Id id : req.getAddSet()) {
 | 
			
		||||
            if (!existing.contains(id)) {
 | 
			
		||||
              add.add(new StarredChange(new StarredChange.Key(me, id)));
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        if (req.getRemoveSet() != null) {
 | 
			
		||||
          for (final Change.Id id : req.getRemoveSet()) {
 | 
			
		||||
            if (existing.contains(id)) {
 | 
			
		||||
              remove.add(new StarredChange(new StarredChange.Key(me, id)));
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (!add.isEmpty() || !remove.isEmpty()) {
 | 
			
		||||
          final Transaction txn = db.beginTransaction();
 | 
			
		||||
          db.starredChanges().insert(add);
 | 
			
		||||
          db.starredChanges().delete(remove);
 | 
			
		||||
          txn.commit();
 | 
			
		||||
        }
 | 
			
		||||
        callback.onSuccess(VoidResult.INSTANCE);
 | 
			
		||||
      } finally {
 | 
			
		||||
        db.close();
 | 
			
		||||
      }
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      callback.onFailure(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public void myStarredChangeIds(final AsyncCallback<Set<Id>> callback) {
 | 
			
		||||
    final Account.Id me = idFromCookie();
 | 
			
		||||
    if (me == null) {
 | 
			
		||||
      callback.onFailure(new IllegalArgumentException("Not signed in"));
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
      final ReviewDb db = schema.open();
 | 
			
		||||
      try {
 | 
			
		||||
        final Set<Change.Id> existing = new HashSet<Change.Id>();
 | 
			
		||||
        for (final StarredChange sc : db.starredChanges().byAccount(me)) {
 | 
			
		||||
          existing.add(sc.getChangeId());
 | 
			
		||||
        }
 | 
			
		||||
        callback.onSuccess(existing);
 | 
			
		||||
      } finally {
 | 
			
		||||
        db.close();
 | 
			
		||||
      }
 | 
			
		||||
    } catch (OrmException e) {
 | 
			
		||||
      callback.onFailure(e);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  private List<ChangeInfo> list(final ResultSet<Change> rs,
 | 
			
		||||
      final Set<Change.Id> starred, final AccountCache accts)
 | 
			
		||||
      throws OrmException {
 | 
			
		||||
    final ArrayList<ChangeInfo> r = new ArrayList<ChangeInfo>();
 | 
			
		||||
    for (final Change c : rs) {
 | 
			
		||||
      r.add(new ChangeInfo(c, accts));
 | 
			
		||||
      final ChangeInfo ci = new ChangeInfo(c, accts);
 | 
			
		||||
      ci.setStarred(starred.contains(ci.getId()));
 | 
			
		||||
      r.add(ci);
 | 
			
		||||
    }
 | 
			
		||||
    return r;
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,12 +20,14 @@ import com.google.gerrit.client.SignedInListener;
 | 
			
		||||
import com.google.gerrit.client.data.ChangeInfo;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Change;
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Change.Id;
 | 
			
		||||
import com.google.gwt.core.client.GWT;
 | 
			
		||||
import com.google.gwt.user.client.Command;
 | 
			
		||||
import com.google.gwt.user.client.DOM;
 | 
			
		||||
import com.google.gwt.user.client.DeferredCommand;
 | 
			
		||||
import com.google.gwt.user.client.Element;
 | 
			
		||||
import com.google.gwt.user.client.Event;
 | 
			
		||||
import com.google.gwt.user.client.History;
 | 
			
		||||
import com.google.gwt.user.client.rpc.AsyncCallback;
 | 
			
		||||
import com.google.gwt.user.client.ui.AbstractImagePrototype;
 | 
			
		||||
import com.google.gwt.user.client.ui.Composite;
 | 
			
		||||
import com.google.gwt.user.client.ui.FlexTable;
 | 
			
		||||
@@ -40,10 +42,12 @@ import com.google.gwt.user.client.ui.SourcesTableEvents;
 | 
			
		||||
import com.google.gwt.user.client.ui.TableListener;
 | 
			
		||||
import com.google.gwt.user.client.ui.Widget;
 | 
			
		||||
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 | 
			
		||||
import com.google.gwtjsonrpc.client.VoidCallback;
 | 
			
		||||
 | 
			
		||||
import java.util.ArrayList;
 | 
			
		||||
import java.util.LinkedHashMap;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
import java.util.Map.Entry;
 | 
			
		||||
 | 
			
		||||
public class ChangeTable extends Composite implements HasFocus {
 | 
			
		||||
@@ -151,13 +155,24 @@ public class ChangeTable extends Composite implements HasFocus {
 | 
			
		||||
 | 
			
		||||
    signedInListener = new SignedInListener() {
 | 
			
		||||
      public void onSignIn() {
 | 
			
		||||
        final int max = table.getRowCount();
 | 
			
		||||
        for (int row = 0; row < max; row++) {
 | 
			
		||||
          final ChangeInfo c = getChangeInfo(row);
 | 
			
		||||
          if (c != null) {
 | 
			
		||||
            setStar(row, c);
 | 
			
		||||
        Util.LIST_SVC.myStarredChangeIds(new AsyncCallback<Set<Change.Id>>() {
 | 
			
		||||
          public void onFailure(final Throwable caught) {
 | 
			
		||||
            GWT.log("ChangeTable.onSignIn myStarredChangeIds failed", caught);
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
          public void onSuccess(final Set<Change.Id> result) {
 | 
			
		||||
            if (result != null) {
 | 
			
		||||
              final int max = table.getRowCount();
 | 
			
		||||
              for (int row = 0; row < max; row++) {
 | 
			
		||||
                final ChangeInfo c = getChangeInfo(row);
 | 
			
		||||
                if (c != null) {
 | 
			
		||||
                  c.setStarred(result.contains(c.getId()));
 | 
			
		||||
                  setStar(row, c);
 | 
			
		||||
                }
 | 
			
		||||
              }
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
        });
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      public void onSignOut() {
 | 
			
		||||
@@ -184,6 +199,10 @@ public class ChangeTable extends Composite implements HasFocus {
 | 
			
		||||
    if (c != null && Gerrit.isSignedIn()) {
 | 
			
		||||
      c.setStarred(!c.isStarred());
 | 
			
		||||
      setStar(row, c);
 | 
			
		||||
 | 
			
		||||
      final ToggleStarRequest req = new ToggleStarRequest();
 | 
			
		||||
      req.toggle(c.getId(), c.isStarred());
 | 
			
		||||
      Util.LIST_SVC.toggleStars(req, VoidCallback.INSTANCE);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,13 @@
 | 
			
		||||
 | 
			
		||||
package com.google.gerrit.client.changes;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.client.data.ChangeInfo;
 | 
			
		||||
import com.google.gerrit.client.ui.AccountScreen;
 | 
			
		||||
import com.google.gwt.core.client.GWT;
 | 
			
		||||
import com.google.gwt.user.client.History;
 | 
			
		||||
import com.google.gwt.user.client.rpc.AsyncCallback;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
public class MineStarredScreen extends AccountScreen {
 | 
			
		||||
@@ -30,4 +36,20 @@ public class MineStarredScreen extends AccountScreen {
 | 
			
		||||
    table.addSection(starred);
 | 
			
		||||
    add(table);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  @Override
 | 
			
		||||
  public void onLoad() {
 | 
			
		||||
    super.onLoad();
 | 
			
		||||
    table.setSavePointerId(History.getToken());
 | 
			
		||||
    Util.LIST_SVC.myStarredChanges(new AsyncCallback<List<ChangeInfo>>() {
 | 
			
		||||
      public void onSuccess(final List<ChangeInfo> result) {
 | 
			
		||||
        starred.display(result);
 | 
			
		||||
        table.finishDisplay();
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      public void onFailure(final Throwable caught) {
 | 
			
		||||
        GWT.log("Fail", caught);
 | 
			
		||||
      }
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,63 @@
 | 
			
		||||
// Copyright 2008 Google Inc.
 | 
			
		||||
//
 | 
			
		||||
// 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.client.changes;
 | 
			
		||||
 | 
			
		||||
import com.google.gerrit.client.reviewdb.Change;
 | 
			
		||||
 | 
			
		||||
import java.util.HashSet;
 | 
			
		||||
import java.util.Set;
 | 
			
		||||
 | 
			
		||||
/** Request parameters to update the changes the user has toggled. */
 | 
			
		||||
public class ToggleStarRequest {
 | 
			
		||||
  protected Set<Change.Id> add;
 | 
			
		||||
  protected Set<Change.Id> remove;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * Request an update to the change's star status.
 | 
			
		||||
   * 
 | 
			
		||||
   * @param id unique id of the change, must not be null.
 | 
			
		||||
   * @param on true if the change should now be starred; false if it should now
 | 
			
		||||
   *        be not starred.
 | 
			
		||||
   */
 | 
			
		||||
  public void toggle(final Change.Id id, final boolean on) {
 | 
			
		||||
    if (on) {
 | 
			
		||||
      if (add == null) {
 | 
			
		||||
        add = new HashSet<Change.Id>();
 | 
			
		||||
      }
 | 
			
		||||
      add.add(id);
 | 
			
		||||
      if (remove != null) {
 | 
			
		||||
        remove.remove(id);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (remove == null) {
 | 
			
		||||
        remove = new HashSet<Change.Id>();
 | 
			
		||||
      }
 | 
			
		||||
      remove.add(id);
 | 
			
		||||
      if (add != null) {
 | 
			
		||||
        add.remove(id);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Get the set of changes which should have stars added; may be null. */
 | 
			
		||||
  public Set<Change.Id> getAddSet() {
 | 
			
		||||
    return add;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Get the set of changes which should have stars removed; may be null. */
 | 
			
		||||
  public Set<Change.Id> getRemoveSet() {
 | 
			
		||||
    return remove;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user