Add additional information in Groups Table.

Add columns for 'Owners', 'Group Type', 'Email Only Authors' and
'Visible To All' into the groups table used by Admin->Groups Screen
and MyGroups Screen. Adding more info to this table helps the
administrators to view the settings and additional info of a group
faster without clicking on each group. This can work as a dashboard
or report that contains the info for all the groups in one place.
As an example, this allows one to quickly find all the groups which
are having emails squelched.

Change-Id: Ia952e9dcecf415c4fce7001a0d28ad4731ff5b1c
This commit is contained in:
Raviteja Sunkara
2011-06-28 20:25:21 +05:30
parent f8d35d7312
commit fccf928042
9 changed files with 70 additions and 19 deletions

View File

@@ -15,9 +15,9 @@
package com.google.gerrit.common.data; package com.google.gerrit.common.data;
import com.google.gerrit.common.auth.SignInRequired; import com.google.gerrit.common.auth.SignInRequired;
import com.google.gerrit.common.data.GroupDetail;
import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.Account;
import com.google.gerrit.reviewdb.AccountExternalId; import com.google.gerrit.reviewdb.AccountExternalId;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.AccountSshKey; import com.google.gerrit.reviewdb.AccountSshKey;
import com.google.gerrit.reviewdb.ContactInformation; import com.google.gerrit.reviewdb.ContactInformation;
import com.google.gerrit.reviewdb.ContributorAgreement; import com.google.gerrit.reviewdb.ContributorAgreement;
@@ -57,7 +57,7 @@ public interface AccountSecurity extends RemoteJsonService {
void myExternalIds(AsyncCallback<List<AccountExternalId>> callback); void myExternalIds(AsyncCallback<List<AccountExternalId>> callback);
@SignInRequired @SignInRequired
void myGroups(AsyncCallback<List<AccountGroup>> callback); void myGroups(AsyncCallback<List<GroupDetail>> callback);
@SignInRequired @SignInRequired
void deleteExternalIds(Set<AccountExternalId.Key> keys, void deleteExternalIds(Set<AccountExternalId.Key> keys,

View File

@@ -14,19 +14,19 @@
package com.google.gerrit.common.data; package com.google.gerrit.common.data;
import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.common.data.GroupDetail;
import java.util.List; import java.util.List;
public class GroupList { public class GroupList {
protected List<AccountGroup> groups; protected List<GroupDetail> groups;
protected boolean canCreateGroup; protected boolean canCreateGroup;
public List<AccountGroup> getGroups() { public List<GroupDetail> getGroups() {
return groups; return groups;
} }
public void setGroups(List<AccountGroup> groups) { public void setGroups(List<GroupDetail> groups) {
this.groups = groups; this.groups = groups;
} }

View File

@@ -16,7 +16,7 @@ package com.google.gerrit.client.account;
import com.google.gerrit.client.admin.GroupTable; import com.google.gerrit.client.admin.GroupTable;
import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.common.data.GroupDetail;
import java.util.List; import java.util.List;
@@ -33,8 +33,8 @@ public class MyGroupsScreen extends SettingsScreen {
@Override @Override
protected void onLoad() { protected void onLoad() {
super.onLoad(); super.onLoad();
Util.ACCOUNT_SEC.myGroups(new ScreenLoadCallback<List<AccountGroup>>(this) { Util.ACCOUNT_SEC.myGroups(new ScreenLoadCallback<List<GroupDetail>>(this) {
public void preDisplay(final List<AccountGroup> result) { public void preDisplay(final List<GroupDetail> result) {
groups.display(result); groups.display(result);
} }
}); });

View File

@@ -71,6 +71,9 @@ public interface AdminConstants extends Constants {
String columnEmailAddress(); String columnEmailAddress();
String columnGroupName(); String columnGroupName();
String columnGroupDescription(); String columnGroupDescription();
String columnGroupType();
String columnGroupNotifications();
String columnGroupVisibleToAll();
String columnBranchName(); String columnBranchName();
String columnBranchRevision(); String columnBranchRevision();

View File

@@ -51,6 +51,9 @@ columnMember = Member
columnEmailAddress = Email Address columnEmailAddress = Email Address
columnGroupName = Group Name columnGroupName = Group Name
columnGroupDescription = Description columnGroupDescription = Description
columnGroupType = Group Type
columnGroupNotifications = Email Only Authors
columnGroupVisibleToAll = Visible To All
columnBranchName = Branch Name columnBranchName = Branch Name
columnBranchRevision = Revision columnBranchRevision = Revision

View File

@@ -16,8 +16,10 @@ package com.google.gerrit.client.admin;
import com.google.gerrit.client.Dispatcher; import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.ui.Hyperlink; import com.google.gerrit.client.ui.Hyperlink;
import com.google.gerrit.client.ui.NavigationTable; import com.google.gerrit.client.ui.NavigationTable;
import com.google.gerrit.common.data.GroupDetail;
import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.event.dom.client.ClickHandler;
@@ -25,6 +27,7 @@ import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.user.client.History; import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwt.user.client.ui.HTMLTable.Cell; import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.Image;
import java.util.List; import java.util.List;
@@ -48,6 +51,10 @@ public class GroupTable extends NavigationTable<AccountGroup> {
table.setText(0, 1, Util.C.columnGroupName()); table.setText(0, 1, Util.C.columnGroupName());
table.setText(0, 2, Util.C.columnGroupDescription()); table.setText(0, 2, Util.C.columnGroupDescription());
table.setText(0, 3, Util.C.headingOwner());
table.setText(0, 4, Util.C.columnGroupType());
table.setText(0, 5, Util.C.columnGroupNotifications());
table.setText(0, 6, Util.C.columnGroupVisibleToAll());
table.addClickHandler(new ClickHandler() { table.addClickHandler(new ClickHandler() {
@Override @Override
public void onClick(ClickEvent event) { public void onClick(ClickEvent event) {
@@ -62,6 +69,10 @@ public class GroupTable extends NavigationTable<AccountGroup> {
final FlexCellFormatter fmt = table.getFlexCellFormatter(); final FlexCellFormatter fmt = table.getFlexCellFormatter();
fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader()); fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader()); fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 5, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 6, Gerrit.RESOURCES.css().dataHeader());
} }
@Override @Override
@@ -74,19 +85,20 @@ public class GroupTable extends NavigationTable<AccountGroup> {
History.newItem(Dispatcher.toGroup(getRowItem(row).getId())); History.newItem(Dispatcher.toGroup(getRowItem(row).getId()));
} }
public void display(final List<AccountGroup> result) { public void display(final List<GroupDetail> result) {
while (1 < table.getRowCount()) while (1 < table.getRowCount())
table.removeRow(table.getRowCount() - 1); table.removeRow(table.getRowCount() - 1);
for (final AccountGroup k : result) { for(GroupDetail detail : result) {
final int row = table.getRowCount(); final int row = table.getRowCount();
table.insertRow(row); table.insertRow(row);
applyDataRowStyle(row); applyDataRowStyle(row);
populate(row, k); populate(row, detail);
} }
} }
void populate(final int row, final AccountGroup k) { void populate(final int row, final GroupDetail detail) {
AccountGroup k = detail.group;
if (enableLink) { if (enableLink) {
table.setWidget(row, 1, new Hyperlink(k.getName(), table.setWidget(row, 1, new Hyperlink(k.getName(),
Dispatcher.toGroup(k.getId()))); Dispatcher.toGroup(k.getId())));
@@ -94,11 +106,23 @@ public class GroupTable extends NavigationTable<AccountGroup> {
table.setText(row, 1, k.getName()); table.setText(row, 1, k.getName());
} }
table.setText(row, 2, k.getDescription()); table.setText(row, 2, k.getDescription());
table.setText(row, 3, detail.ownerGroup.getName());
table.setText(row, 4, k.getType().toString());
if (k.isEmailOnlyAuthors()) {
table.setWidget(row, 5, new Image(Gerrit.RESOURCES.greenCheck()));
}
if (k.isVisibleToAll()) {
table.setWidget(row, 6, new Image(Gerrit.RESOURCES.greenCheck()));
}
final FlexCellFormatter fmt = table.getFlexCellFormatter(); final FlexCellFormatter fmt = table.getFlexCellFormatter();
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell()); fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().dataCell());
fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().groupName()); fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().groupName());
fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell()); fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().dataCell());
fmt.addStyleName(row, 3, Gerrit.RESOURCES.css().dataCell());
fmt.addStyleName(row, 4, Gerrit.RESOURCES.css().dataCell());
fmt.addStyleName(row, 5, Gerrit.RESOURCES.css().dataCell());
fmt.addStyleName(row, 6, Gerrit.RESOURCES.css().dataCell());
setRowItem(row, k); setRowItem(row, k);
} }

View File

@@ -15,10 +15,12 @@
package com.google.gerrit.httpd.rpc.account; package com.google.gerrit.httpd.rpc.account;
import com.google.gerrit.common.data.AccountSecurity; import com.google.gerrit.common.data.AccountSecurity;
import com.google.gerrit.common.data.GroupDetail;
import com.google.gerrit.common.errors.ContactInformationStoreException; import com.google.gerrit.common.errors.ContactInformationStoreException;
import com.google.gerrit.common.errors.InvalidSshKeyException; import com.google.gerrit.common.errors.InvalidSshKeyException;
import com.google.gerrit.common.errors.NameAlreadyUsedException; import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.common.errors.NoSuchEntityException; import com.google.gerrit.common.errors.NoSuchEntityException;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.httpd.rpc.BaseServiceImplementation; import com.google.gerrit.httpd.rpc.BaseServiceImplementation;
import com.google.gerrit.httpd.rpc.Handler; import com.google.gerrit.httpd.rpc.Handler;
import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.Account;
@@ -39,6 +41,7 @@ import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.ChangeUserName; import com.google.gerrit.server.account.ChangeUserName;
import com.google.gerrit.server.account.ClearPassword; import com.google.gerrit.server.account.ClearPassword;
import com.google.gerrit.server.account.GeneratePassword; import com.google.gerrit.server.account.GeneratePassword;
import com.google.gerrit.server.account.GroupDetailFactory;
import com.google.gerrit.server.account.Realm; import com.google.gerrit.server.account.Realm;
import com.google.gerrit.server.config.AuthConfig; import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.contact.ContactStore; import com.google.gerrit.server.contact.ContactStore;
@@ -58,6 +61,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -82,6 +86,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
private final DeleteExternalIds.Factory deleteExternalIdsFactory; private final DeleteExternalIds.Factory deleteExternalIdsFactory;
private final ExternalIdDetailFactory.Factory externalIdDetailFactory; private final ExternalIdDetailFactory.Factory externalIdDetailFactory;
private final MyGroupsFactory.Factory myGroupsFactory; private final MyGroupsFactory.Factory myGroupsFactory;
private final GroupDetailFactory.Factory groupDetailFactory;
@Inject @Inject
AccountSecurityImpl(final Provider<ReviewDb> schema, AccountSecurityImpl(final Provider<ReviewDb> schema,
@@ -95,7 +100,8 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
final ChangeUserName.CurrentUser changeUserNameFactory, final ChangeUserName.CurrentUser changeUserNameFactory,
final DeleteExternalIds.Factory deleteExternalIdsFactory, final DeleteExternalIds.Factory deleteExternalIdsFactory,
final ExternalIdDetailFactory.Factory externalIdDetailFactory, final ExternalIdDetailFactory.Factory externalIdDetailFactory,
final MyGroupsFactory.Factory myGroupsFactory) { final MyGroupsFactory.Factory myGroupsFactory,
final GroupDetailFactory.Factory groupDetailFactory) {
super(schema, currentUser); super(schema, currentUser);
contactStore = cs; contactStore = cs;
authConfig = ac; authConfig = ac;
@@ -115,6 +121,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
this.deleteExternalIdsFactory = deleteExternalIdsFactory; this.deleteExternalIdsFactory = deleteExternalIdsFactory;
this.externalIdDetailFactory = externalIdDetailFactory; this.externalIdDetailFactory = externalIdDetailFactory;
this.myGroupsFactory = myGroupsFactory; this.myGroupsFactory = myGroupsFactory;
this.groupDetailFactory = groupDetailFactory;
} }
public void mySshKeys(final AsyncCallback<List<AccountSshKey>> callback) { public void mySshKeys(final AsyncCallback<List<AccountSshKey>> callback) {
@@ -198,8 +205,17 @@ class AccountSecurityImpl extends BaseServiceImplementation implements
} }
@Override @Override
public void myGroups(final AsyncCallback<List<AccountGroup>> callback) { public void myGroups(final AsyncCallback<List<GroupDetail>> callback) {
myGroupsFactory.create().to(callback); run(callback, new Action<List<GroupDetail>>() {
public List<GroupDetail> run(final ReviewDb db) throws OrmException,
NoSuchGroupException, Failure {
List<GroupDetail> groupDetails = new ArrayList<GroupDetail>();
for(AccountGroup group : myGroupsFactory.create().call()) {
groupDetails.add(groupDetailFactory.create(group.getId()).call());
}
return groupDetails;
}
});
} }
public void deleteExternalIds(final Set<AccountExternalId.Key> keys, public void deleteExternalIds(final Set<AccountExternalId.Key> keys,

View File

@@ -91,7 +91,8 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements
public void visibleGroups(final AsyncCallback<GroupList> callback) { public void visibleGroups(final AsyncCallback<GroupList> callback) {
run(callback, new Action<GroupList>() { run(callback, new Action<GroupList>() {
public GroupList run(ReviewDb db) throws OrmException { public GroupList run(ReviewDb db) throws OrmException,
NoSuchGroupException {
final IdentifiedUser user = identifiedUser.get(); final IdentifiedUser user = identifiedUser.get();
final List<AccountGroup> list; final List<AccountGroup> list;
if (user.getCapabilities().canAdministrateServer()) { if (user.getCapabilities().canAdministrateServer()) {
@@ -111,8 +112,12 @@ class GroupAdminServiceImpl extends BaseServiceImplementation implements
} }
}); });
List<GroupDetail> l = new ArrayList<GroupDetail>();
for(AccountGroup group : list) {
l.add(groupDetailFactory.create(group.getId()).call());
}
GroupList res = new GroupList(); GroupList res = new GroupList();
res.setGroups(list); res.setGroups(l);
res.setCanCreateGroup(user.getCapabilities().canCreateGroup()); res.setCanCreateGroup(user.getCapabilities().canCreateGroup());
return res; return res;
} }

View File

@@ -41,7 +41,7 @@ class MyGroupsFactory extends Handler<List<AccountGroup>> {
} }
@Override @Override
public List<AccountGroup> call() throws Exception { public List<AccountGroup> call() {
final Set<AccountGroup.UUID> effective = user.getEffectiveGroups(); final Set<AccountGroup.UUID> effective = user.getEffectiveGroups();
final int cnt = effective.size(); final int cnt = effective.size();
final List<AccountGroup> groupList = new ArrayList<AccountGroup>(cnt); final List<AccountGroup> groupList = new ArrayList<AccountGroup>(cnt);