Add a view of the changes with unpublished drafts by this user

This makes it easier to see which changes you might want to
go revisit, because you have drafts you haven't yet published
to the world.

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2009-01-16 13:05:19 -08:00
parent 684d8db648
commit dd89f538d7
14 changed files with 183 additions and 62 deletions

View File

@@ -115,6 +115,9 @@ ON contributor_agreements (active, short_name);
-- ********************************************************************* -- *********************************************************************
-- PatchLineCommentAccess -- PatchLineCommentAccess
-- @PrimaryKey covers: published, draft -- @PrimaryKey covers: published, draft
CREATE INDEX patch_comment_drafts
ON patch_comments (author)
WHERE status = 'd';
-- ********************************************************************* -- *********************************************************************

View File

@@ -305,6 +305,7 @@ public class Gerrit implements EntryPoint {
if (signedIn) { if (signedIn) {
m = new MenuBar(true); m = new MenuBar(true);
addLink(m, C.menuMyChanges(), Link.MINE); addLink(m, C.menuMyChanges(), Link.MINE);
addLink(m, C.menyMyDrafts(), Link.MINE_DRAFTS);
addLink(m, C.menuMyUnclaimedChanges(), Link.MINE_UNCLAIMED); addLink(m, C.menuMyUnclaimedChanges(), Link.MINE_UNCLAIMED);
addLink(m, C.menuMyStarredChanges(), Link.MINE_STARRED); addLink(m, C.menuMyStarredChanges(), Link.MINE_STARRED);
menuBar.addItem(C.menuMine(), m); menuBar.addItem(C.menuMine(), m);

View File

@@ -37,6 +37,7 @@ public interface GerritConstants extends Constants {
String menuMine(); String menuMine();
String menuMyChanges(); String menuMyChanges();
String menyMyDrafts();
String menuMyUnclaimedChanges(); String menuMyUnclaimedChanges();
String menuMyStarredChanges(); String menuMyStarredChanges();

View File

@@ -16,8 +16,9 @@ menuAll = All
menuAllUnclaimedChanges = Unclaimed Changes menuAllUnclaimedChanges = Unclaimed Changes
menuAllRecentChanges = Recent Changes menuAllRecentChanges = Recent Changes
menuMine = Mine menuMine = My
menuMyChanges = My Changes menuMyChanges = Changes
menyMyDrafts = Drafts
menuMyUnclaimedChanges = Unclaimed Changes menuMyUnclaimedChanges = Unclaimed Changes
menuMyStarredChanges = Starred Changes menuMyStarredChanges = Starred Changes

View File

@@ -23,6 +23,7 @@ import com.google.gerrit.client.admin.ProjectAdminScreen;
import com.google.gerrit.client.admin.ProjectListScreen; import com.google.gerrit.client.admin.ProjectListScreen;
import com.google.gerrit.client.changes.AccountDashboardScreen; import com.google.gerrit.client.changes.AccountDashboardScreen;
import com.google.gerrit.client.changes.ChangeScreen; import com.google.gerrit.client.changes.ChangeScreen;
import com.google.gerrit.client.changes.MineDraftsScreen;
import com.google.gerrit.client.changes.MineStarredScreen; import com.google.gerrit.client.changes.MineStarredScreen;
import com.google.gerrit.client.changes.PublishCommentScreen; import com.google.gerrit.client.changes.PublishCommentScreen;
import com.google.gerrit.client.data.AccountInfo; import com.google.gerrit.client.data.AccountInfo;
@@ -51,6 +52,7 @@ public class Link implements HistoryListener {
public static final String MINE = "mine"; public static final String MINE = "mine";
public static final String MINE_UNCLAIMED = "mine,unclaimed"; public static final String MINE_UNCLAIMED = "mine,unclaimed";
public static final String MINE_STARRED = "mine,starred"; public static final String MINE_STARRED = "mine,starred";
public static final String MINE_DRAFTS = "mine,drafts";
public static final String ALL = "all"; public static final String ALL = "all";
public static final String ALL_OPEN = "all,open"; public static final String ALL_OPEN = "all,open";
@@ -129,9 +131,13 @@ public class Link implements HistoryListener {
if (MINE.equals(token)) { if (MINE.equals(token)) {
return new AccountDashboardScreen(Common.getAccountId()); return new AccountDashboardScreen(Common.getAccountId());
} }
if (token.startsWith("mine,")) {
if (MINE_STARRED.equals(token)) { if (MINE_STARRED.equals(token)) {
return new MineStarredScreen(); return new MineStarredScreen();
}
if (MINE_DRAFTS.equals(token)) {
return new MineDraftsScreen();
}
} }
if (token.startsWith("patch,")) { if (token.startsWith("patch,")) {

View File

@@ -25,6 +25,7 @@ public interface ChangeConstants extends Constants {
String changesRecentlyClosed(); String changesRecentlyClosed();
String starredHeading(); String starredHeading();
String draftsHeading();
String changeTableColumnID(); String changeTableColumnID();
String changeTableColumnSubject(); String changeTableColumnSubject();

View File

@@ -4,6 +4,7 @@ statusLongMerged = Merged
statusLongAbandoned = Abandoned statusLongAbandoned = Abandoned
starredHeading = Starred Changes starredHeading = Starred Changes
draftsHeading = Changes with unpublished drafts
changesRecentlyClosed = Recently closed changes changesRecentlyClosed = Recently closed changes
changeTableColumnID = ID changeTableColumnID = ID

View File

@@ -15,7 +15,7 @@
package com.google.gerrit.client.changes; package com.google.gerrit.client.changes;
import com.google.gerrit.client.data.AccountDashboardInfo; import com.google.gerrit.client.data.AccountDashboardInfo;
import com.google.gerrit.client.data.MineStarredInfo; import com.google.gerrit.client.data.SingleListChangeInfo;
import com.google.gerrit.client.reviewdb.Account; import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.Change; import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.rpc.SignInRequired; import com.google.gerrit.client.rpc.SignInRequired;
@@ -31,7 +31,11 @@ public interface ChangeListService extends RemoteJsonService {
/** Get the changes starred by the caller. */ /** Get the changes starred by the caller. */
@SignInRequired @SignInRequired
void myStarredChanges(AsyncCallback<MineStarredInfo> callback); void myStarredChanges(AsyncCallback<SingleListChangeInfo> callback);
/** Get the changes with unpublished drafts by the caller. */
@SignInRequired
void myDraftChanges(AsyncCallback<SingleListChangeInfo> callback);
/** Get the ids of all changes starred by the caller. */ /** Get the ids of all changes starred by the caller. */
@SignInRequired @SignInRequired

View File

@@ -17,10 +17,11 @@ package com.google.gerrit.client.changes;
import com.google.gerrit.client.data.AccountDashboardInfo; import com.google.gerrit.client.data.AccountDashboardInfo;
import com.google.gerrit.client.data.AccountInfoCacheFactory; import com.google.gerrit.client.data.AccountInfoCacheFactory;
import com.google.gerrit.client.data.ChangeInfo; import com.google.gerrit.client.data.ChangeInfo;
import com.google.gerrit.client.data.MineStarredInfo; import com.google.gerrit.client.data.SingleListChangeInfo;
import com.google.gerrit.client.reviewdb.Account; import com.google.gerrit.client.reviewdb.Account;
import com.google.gerrit.client.reviewdb.Change; import com.google.gerrit.client.reviewdb.Change;
import com.google.gerrit.client.reviewdb.ChangeAccess; import com.google.gerrit.client.reviewdb.ChangeAccess;
import com.google.gerrit.client.reviewdb.PatchLineComment;
import com.google.gerrit.client.reviewdb.ReviewDb; import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.reviewdb.StarredChange; import com.google.gerrit.client.reviewdb.StarredChange;
import com.google.gerrit.client.reviewdb.Change.Id; import com.google.gerrit.client.reviewdb.Change.Id;
@@ -73,10 +74,11 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
}); });
} }
public void myStarredChanges(final AsyncCallback<MineStarredInfo> callback) { public void myStarredChanges(
run(callback, new Action<MineStarredInfo>() { final AsyncCallback<SingleListChangeInfo> callback) {
public MineStarredInfo run(final ReviewDb db) throws OrmException, run(callback, new Action<SingleListChangeInfo>() {
Failure { public SingleListChangeInfo run(final ReviewDb db)
throws OrmException, Failure {
final Account.Id me = Common.getAccountId(); final Account.Id me = Common.getAccountId();
final AccountInfoCacheFactory ac = new AccountInfoCacheFactory(db); final AccountInfoCacheFactory ac = new AccountInfoCacheFactory(db);
final Account user = ac.get(me); final Account user = ac.get(me);
@@ -84,10 +86,37 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
throw new Failure(new NoSuchEntityException()); throw new Failure(new NoSuchEntityException());
} }
final MineStarredInfo d = new MineStarredInfo(me); final SingleListChangeInfo d = new SingleListChangeInfo();
final Set<Change.Id> starred = starredBy(db, me); final Set<Change.Id> starred = starredBy(db, me);
d.setStarred(filter(db.changes().get(starred), starred, ac)); d.setChanges(filter(db.changes().get(starred), starred, ac));
Collections.sort(d.getStarred(), new Comparator<ChangeInfo>() { Collections.sort(d.getChanges(), new Comparator<ChangeInfo>() {
public int compare(final ChangeInfo o1, final ChangeInfo o2) {
return o1.getLastUpdatedOn().compareTo(o2.getLastUpdatedOn());
}
});
d.setAccounts(ac.create());
return d;
}
});
}
public void myDraftChanges(
final AsyncCallback<SingleListChangeInfo> callback) {
run(callback, new Action<SingleListChangeInfo>() {
public SingleListChangeInfo run(final ReviewDb db)
throws OrmException, Failure {
final Account.Id me = Common.getAccountId();
final AccountInfoCacheFactory ac = new AccountInfoCacheFactory(db);
final Account user = ac.get(me);
if (user == null) {
throw new Failure(new NoSuchEntityException());
}
final SingleListChangeInfo d = new SingleListChangeInfo();
final Set<Change.Id> starred = starredBy(db, me);
final Set<Change.Id> drafted = draftedBy(db, me);
d.setChanges(filter(db.changes().get(drafted), starred, ac));
Collections.sort(d.getChanges(), new Comparator<ChangeInfo>() {
public int compare(final ChangeInfo o1, final ChangeInfo o2) { public int compare(final ChangeInfo o1, final ChangeInfo o2) {
return o1.getLastUpdatedOn().compareTo(o2.getLastUpdatedOn()); return o1.getLastUpdatedOn().compareTo(o2.getLastUpdatedOn());
} }
@@ -165,4 +194,17 @@ public class ChangeListServiceImpl extends BaseServiceImplementation implements
} }
return existing; return existing;
} }
private static Set<Change.Id> draftedBy(final ReviewDb db, final Account.Id me)
throws OrmException {
final Set<Change.Id> existing = new HashSet<Change.Id>();
if (me != null) {
for (final PatchLineComment sc : db.patchComments().draftByAuthor(me)) {
final Change.Id c =
sc.getKey().getParentKey().getParentKey().getParentKey();
existing.add(c);
}
}
return existing;
}
} }

View File

@@ -0,0 +1,37 @@
// 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.Link;
import com.google.gerrit.client.data.SingleListChangeInfo;
import com.google.gerrit.client.rpc.GerritCallback;
public class MineDraftsScreen extends MineSingleListScreen {
public MineDraftsScreen() {
super(Util.C.draftsHeading(), Link.MINE_DRAFTS);
}
@Override
public void onLoad() {
super.onLoad();
Util.LIST_SVC
.myDraftChanges(new GerritCallback<SingleListChangeInfo>() {
public void onSuccess(final SingleListChangeInfo result) {
display(result);
}
});
}
}

View File

@@ -0,0 +1,49 @@
// 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.data.SingleListChangeInfo;
import com.google.gerrit.client.ui.AccountScreen;
public class MineSingleListScreen extends AccountScreen {
private final String anchor;
private ChangeTable table;
private ChangeTable.Section drafts;
public MineSingleListScreen(final String title, final String historyToken) {
super(title);
anchor = historyToken;
table = new ChangeTable();
drafts = new ChangeTable.Section();
table.addSection(drafts);
table.setSavePointerId(anchor);
add(table);
}
@Override
public Object getScreenCacheToken() {
return anchor;
}
protected void display(final SingleListChangeInfo result) {
table.setAccountInfoCache(result.getAccounts());
drafts.display(result.getChanges());
table.finishDisplay(true);
}
}

View File

@@ -15,41 +15,23 @@
package com.google.gerrit.client.changes; package com.google.gerrit.client.changes;
import com.google.gerrit.client.Link; import com.google.gerrit.client.Link;
import com.google.gerrit.client.data.MineStarredInfo; import com.google.gerrit.client.data.SingleListChangeInfo;
import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.AccountScreen;
public class MineStarredScreen extends AccountScreen { public class MineStarredScreen extends MineSingleListScreen {
private ChangeTable table;
private ChangeTable.Section starred;
public MineStarredScreen() { public MineStarredScreen() {
super(Util.C.starredHeading()); super(Util.C.starredHeading(), Link.MINE_STARRED);
table = new ChangeTable();
starred = new ChangeTable.Section();
table.addSection(starred);
table.setSavePointerId(Link.MINE_STARRED);
add(table);
}
@Override
public Object getScreenCacheToken() {
return Link.MINE_STARRED;
} }
@Override @Override
public void onLoad() { public void onLoad() {
super.onLoad(); super.onLoad();
Util.LIST_SVC.myStarredChanges(new GerritCallback<MineStarredInfo>() { Util.LIST_SVC
public void onSuccess(final MineStarredInfo result) { .myStarredChanges(new GerritCallback<SingleListChangeInfo>() {
table.setAccountInfoCache(result.getAccounts()); public void onSuccess(final SingleListChangeInfo result) {
starred.display(result.getStarred()); display(result);
table.finishDisplay(true); }
} });
});
} }
} }

View File

@@ -14,22 +14,14 @@
package com.google.gerrit.client.data; package com.google.gerrit.client.data;
import com.google.gerrit.client.changes.MineStarredScreen;
import com.google.gerrit.client.reviewdb.Account;
import java.util.List; import java.util.List;
/** Summary information needed for {@link MineStarredScreen}. */ /** Summary information needed for screens showing a single list of changes}. */
public class MineStarredInfo { public class SingleListChangeInfo {
protected AccountInfoCache accounts; protected AccountInfoCache accounts;
protected Account.Id owner; protected List<ChangeInfo> changes;
protected List<ChangeInfo> starred;
protected MineStarredInfo() { public SingleListChangeInfo() {
}
public MineStarredInfo(final Account.Id forUser) {
owner = forUser;
} }
public AccountInfoCache getAccounts() { public AccountInfoCache getAccounts() {
@@ -40,15 +32,11 @@ public class MineStarredInfo {
accounts = ac; accounts = ac;
} }
public Account.Id getOwner() { public List<ChangeInfo> getChanges() {
return owner; return changes;
} }
public List<ChangeInfo> getStarred() { public void setChanges(List<ChangeInfo> c) {
return starred; changes = c;
}
public void setStarred(List<ChangeInfo> c) {
starred = c;
} }
} }

View File

@@ -40,4 +40,9 @@ public interface PatchLineCommentAccess extends
+ "' AND author = ? ORDER BY lineNbr,writtenOn") + "' AND author = ? ORDER BY lineNbr,writtenOn")
ResultSet<PatchLineComment> draft(Patch.Key patch, Account.Id author) ResultSet<PatchLineComment> draft(Patch.Key patch, Account.Id author)
throws OrmException; throws OrmException;
@Query("WHERE status = '" + PatchLineComment.STATUS_DRAFT
+ "' AND author = ?")
ResultSet<PatchLineComment> draftByAuthor(Account.Id author)
throws OrmException;
} }