Allow groups to be renamed if the user is an owner

Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
Shawn O. Pearce
2008-12-30 08:36:36 -08:00
parent cf4fdbd57d
commit 60e9a606f3
11 changed files with 190 additions and 81 deletions

View File

@@ -27,6 +27,7 @@ public interface GerritConstants extends Constants {
String notFoundTitle();
String notFoundBody();
String nameAlreadyUsedBody();
String menuAll();
String menuAllUnclaimedChanges();

View File

@@ -8,6 +8,7 @@ errorDialogClose = Close
notFoundTitle = Not Found
notFoundBody = The page you requested was not found.
nameAlreadyUsedBody = The name is already in use.
menuAll = All
menuAllUnclaimedChanges = Unclaimed Changes

View File

@@ -48,8 +48,12 @@ public class AccountGroupScreen extends Screen {
private AccountInfoCache accounts = AccountInfoCache.empty();
private MemberTable members;
private TextBox groupNameTxt;
private Button saveName;
private TextArea descTxt;
private Button saveDesc;
private Button addMember;
private TextBox nameTxtBox;
private SuggestBox nameTxt;
@@ -66,6 +70,7 @@ public class AccountGroupScreen extends Screen {
}
enableForm(false);
saveName.setEnabled(false);
saveDesc.setEnabled(false);
super.onLoad();
@@ -73,6 +78,7 @@ public class AccountGroupScreen extends Screen {
new GerritCallback<AccountGroupDetail>() {
public void onSuccess(final AccountGroupDetail result) {
enableForm(true);
saveName.setEnabled(false);
saveDesc.setEnabled(false);
display(result);
}
@@ -80,6 +86,7 @@ public class AccountGroupScreen extends Screen {
}
private void enableForm(final boolean on) {
groupNameTxt.setEnabled(on);
descTxt.setEnabled(on);
addMember.setEnabled(on);
nameTxtBox.setEnabled(on);
@@ -87,95 +94,123 @@ public class AccountGroupScreen extends Screen {
}
private void initUI() {
{
final VerticalPanel vp = new VerticalPanel();
final Label descHdr = new Label(Util.C.headingDescription());
descHdr.setStyleName("gerrit-SmallHeading");
vp.add(descHdr);
initName();
initDescription();
initMemberList();
}
descTxt = new TextArea();
descTxt.setVisibleLines(6);
descTxt.setCharacterWidth(60);
new TextSaveButtonListener(descTxt, saveDesc);
vp.add(descTxt);
private void initName() {
final VerticalPanel vp = new VerticalPanel();
saveDesc = new Button(Util.C.buttonSaveDescription());
saveDesc.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
final String txt = descTxt.getText().trim();
Util.GROUP_SVC.changeGroupDescription(groupId, txt,
new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) {
saveDesc.setEnabled(false);
}
});
groupNameTxt = new TextBox();
groupNameTxt.setVisibleLength(60);
vp.add(groupNameTxt);
saveName = new Button(Util.C.buttonRenameGroup());
saveName.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
final String newName = groupNameTxt.getText().trim();
Util.GROUP_SVC.renameGroup(groupId, newName,
new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) {
saveName.setEnabled(false);
setTitleText(Util.M.group(newName));
}
});
}
});
vp.add(saveName);
add(vp);
new TextSaveButtonListener(groupNameTxt, saveName);
}
private void initDescription() {
final VerticalPanel vp = new VerticalPanel();
final Label descHdr = new Label(Util.C.headingDescription());
descHdr.setStyleName("gerrit-SmallHeading");
vp.add(descHdr);
descTxt = new TextArea();
descTxt.setVisibleLines(6);
descTxt.setCharacterWidth(60);
vp.add(descTxt);
saveDesc = new Button(Util.C.buttonSaveDescription());
saveDesc.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
final String txt = descTxt.getText().trim();
Util.GROUP_SVC.changeGroupDescription(groupId, txt,
new GerritCallback<VoidResult>() {
public void onSuccess(final VoidResult result) {
saveDesc.setEnabled(false);
}
});
}
});
vp.add(saveDesc);
add(vp);
new TextSaveButtonListener(descTxt, saveDesc);
}
private void initMemberList() {
final Label memberHdr = new Label(Util.C.headingMembers());
memberHdr.setStyleName("gerrit-SmallHeading");
final FlowPanel addPanel = new FlowPanel();
addPanel.setStyleName("gerrit-ProjectWatchPanel-AddPanel");
nameTxtBox = new TextBox();
nameTxt = new SuggestBox(new AccountSuggestOracle(), nameTxtBox);
nameTxtBox.setVisibleLength(50);
nameTxtBox.setText(Util.C.defaultAccountName());
nameTxtBox.addStyleName("gerrit-InputFieldTypeHint");
nameTxtBox.addFocusListener(new FocusListenerAdapter() {
@Override
public void onFocus(Widget sender) {
if (Util.C.defaultAccountName().equals(nameTxtBox.getText())) {
nameTxtBox.setText("");
nameTxtBox.removeStyleName("gerrit-InputFieldTypeHint");
}
});
vp.add(saveDesc);
add(vp);
}
}
{
final Label memberHdr = new Label(Util.C.headingMembers());
memberHdr.setStyleName("gerrit-SmallHeading");
add(memberHdr);
}
{
final FlowPanel fp = new FlowPanel();
fp.setStyleName("gerrit-ProjectWatchPanel-AddPanel");
nameTxtBox = new TextBox();
nameTxt = new SuggestBox(new AccountSuggestOracle(), nameTxtBox);
nameTxtBox.setVisibleLength(50);
nameTxtBox.setText(Util.C.defaultAccountName());
nameTxtBox.addStyleName("gerrit-InputFieldTypeHint");
nameTxtBox.addFocusListener(new FocusListenerAdapter() {
@Override
public void onFocus(Widget sender) {
if (Util.C.defaultAccountName().equals(nameTxtBox.getText())) {
nameTxtBox.setText("");
nameTxtBox.removeStyleName("gerrit-InputFieldTypeHint");
}
@Override
public void onLostFocus(Widget sender) {
if ("".equals(nameTxtBox.getText())) {
nameTxtBox.setText(Util.C.defaultAccountName());
nameTxtBox.addStyleName("gerrit-InputFieldTypeHint");
}
}
});
addPanel.add(nameTxt);
@Override
public void onLostFocus(Widget sender) {
if ("".equals(nameTxtBox.getText())) {
nameTxtBox.setText(Util.C.defaultAccountName());
nameTxtBox.addStyleName("gerrit-InputFieldTypeHint");
}
}
});
fp.add(nameTxt);
addMember = new Button(Util.C.buttonAddGroupMember());
addMember.addClickListener(new ClickListener() {
public void onClick(final Widget sender) {
doAddNew();
}
});
fp.add(addMember);
add(fp);
}
addMember = new Button(Util.C.buttonAddGroupMember());
addMember.addClickListener(new ClickListener() {
public void onClick(final Widget sender) {
doAddNew();
}
});
addPanel.add(addMember);
members = new MemberTable();
delMember = new Button(Util.C.buttonDeleteGroupMembers());
delMember.addClickListener(new ClickListener() {
public void onClick(final Widget sender) {
members.deleteChecked();
}
});
add(memberHdr);
add(addPanel);
add(members);
{
final FlowPanel fp = new FlowPanel();
delMember = new Button(Util.C.buttonDeleteGroupMembers());
delMember.addClickListener(new ClickListener() {
public void onClick(final Widget sender) {
members.deleteChecked();
}
});
fp.add(delMember);
add(fp);
}
add(delMember);
}
private void display(final AccountGroupDetail result) {
setTitleText(Util.M.group(result.group.getName()));
groupNameTxt.setText(result.group.getName());
descTxt.setText(result.group.getDescription());
accounts = result.accounts;
members.display(result.members);

View File

@@ -22,6 +22,7 @@ public interface AdminConstants extends Constants {
String buttonDeleteGroupMembers();
String buttonAddGroupMember();
String buttonSaveDescription();
String buttonRenameGroup();
String headingDescription();
String headingMembers();

View File

@@ -2,6 +2,7 @@ defaultAccountName = Name or Email
buttonDeleteGroupMembers = Delete
buttonAddGroupMember = Add
buttonRenameGroup = Rename Group
buttonSaveDescription = Save Description
headingDescription = Description

View File

@@ -32,6 +32,10 @@ public interface GroupAdminService extends RemoteJsonService {
void changeGroupDescription(AccountGroup.Id groupId, String description,
AsyncCallback<VoidResult> callback);
@SignInRequired
void renameGroup(AccountGroup.Id groupId, String newName,
AsyncCallback<VoidResult> callback);
@SignInRequired
void addGroupMember(AccountGroup.Id groupId, String nameOrEmail,
AsyncCallback<AccountGroupDetail> callback);

View File

@@ -20,6 +20,7 @@ import com.google.gerrit.client.reviewdb.AccountGroup;
import com.google.gerrit.client.reviewdb.AccountGroupMember;
import com.google.gerrit.client.reviewdb.ReviewDb;
import com.google.gerrit.client.rpc.BaseServiceImplementation;
import com.google.gerrit.client.rpc.NameAlreadyUsedException;
import com.google.gerrit.client.rpc.NoSuchEntityException;
import com.google.gerrit.client.rpc.RpcUtil;
import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -70,6 +71,28 @@ public class GroupAdminServiceImpl extends BaseServiceImplementation implements
});
}
public void renameGroup(final AccountGroup.Id groupId, final String newName,
final AsyncCallback<VoidResult> callback) {
run(callback, new Action<VoidResult>() {
public VoidResult run(final ReviewDb db) throws OrmException, Failure {
assertAmGroupOwner(db, groupId);
final AccountGroup group = db.accountGroups().get(groupId);
if (group == null) {
throw new Failure(new NoSuchEntityException());
}
final AccountGroup.NameKey nameKey = new AccountGroup.NameKey(newName);
if (!nameKey.equals(group.getNameKey())) {
if (db.accountGroups().get(nameKey) != null) {
throw new Failure(new NameAlreadyUsedException());
}
group.setNameKey(nameKey);
db.accountGroups().update(Collections.singleton(group));
}
return VoidResult.INSTANCE;
}
});
}
public void addGroupMember(final AccountGroup.Id groupId,
final String nameOrEmail, final AsyncCallback<AccountGroupDetail> callback) {
run(callback, new Action<AccountGroupDetail>() {

View File

@@ -100,6 +100,14 @@ public final class AccountGroup {
return name.get();
}
public AccountGroup.NameKey getNameKey() {
return name;
}
public void setNameKey(final AccountGroup.NameKey nameKey) {
name = nameKey;
}
public String getDescription() {
return description;
}

View File

@@ -20,10 +20,10 @@ import com.google.gwtorm.client.PrimaryKey;
import com.google.gwtorm.client.SecondaryKey;
public interface AccountGroupAccess extends
Access<AccountGroup, AccountGroup.NameKey> {
@PrimaryKey("name")
AccountGroup get(AccountGroup.NameKey name) throws OrmException;
@SecondaryKey("groupId")
Access<AccountGroup, AccountGroup.Id> {
@PrimaryKey("groupId")
AccountGroup get(AccountGroup.Id id) throws OrmException;
@SecondaryKey("name")
AccountGroup get(AccountGroup.NameKey name) throws OrmException;
}

View File

@@ -30,6 +30,9 @@ public abstract class GerritCallback<T> implements AsyncCallback<T> {
} else if (isNoSuchEntity(caught)) {
new ErrorDialog(Gerrit.C.notFoundBody()).center();
} else if (isNameAlreadyUsed(caught)) {
new ErrorDialog(Gerrit.C.nameAlreadyUsedBody()).center();
} else if (caught instanceof ServerUnavailableException) {
new ErrorDialog(RpcUtil.C.errorServerUnavailable()).center();
@@ -54,4 +57,12 @@ public abstract class GerritCallback<T> implements AsyncCallback<T> {
return caught instanceof RemoteJsonException
&& caught.getMessage().equals(NoSuchEntityException.MESSAGE);
}
public static boolean isNameAlreadyUsed(final Throwable caught) {
if (caught instanceof NameAlreadyUsedException) {
return true;
}
return caught instanceof RemoteJsonException
&& caught.getMessage().equals(NameAlreadyUsedException.MESSAGE);
}
}

View File

@@ -0,0 +1,24 @@
// 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.rpc;
/** Error indicating entity name is already taken by another entity. */
public class NameAlreadyUsedException extends Exception {
public static final String MESSAGE = "Name Already Used";
public NameAlreadyUsedException() {
super(MESSAGE);
}
}