Allow Access rights to be edited by clicking on them.

When an access right is clicked on, load the content of the
right into the "add right" form.  This allows a user to edit
the contents and click add.  Depending on the type of the
modification, the right will either be added, or if
appropriate, it will replace the old right.  Also factor out
the "add right" panel into a new class: AccessRightEditor.
Refactor and clarify much of the operation of this class.

Bug: issue 558
Change-Id: Ifbcf3100a2a629a5b8774b03c436ca0b7e5995d4
This commit is contained in:
Martin Fick
2010-08-20 16:44:39 -06:00
parent a4dbdbf4cd
commit 54fc12f950
4 changed files with 468 additions and 280 deletions

View File

@@ -18,7 +18,6 @@ import com.google.gerrit.client.Dispatcher;
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.rpc.GerritCallback;
import com.google.gerrit.client.rpc.ScreenLoadCallback;
import com.google.gerrit.client.ui.AccountGroupSuggestOracle;
import com.google.gerrit.client.ui.FancyFlexTable;
import com.google.gerrit.client.ui.Hyperlink;
import com.google.gerrit.client.ui.SmallHeading;
@@ -27,31 +26,19 @@ import com.google.gerrit.common.data.GerritConfig;
import com.google.gerrit.common.data.InheritedRefRight;
import com.google.gerrit.common.data.ProjectDetail;
import com.google.gerrit.reviewdb.AccountGroup;
import com.google.gerrit.reviewdb.ApprovalCategory;
import com.google.gerrit.reviewdb.ApprovalCategoryValue;
import com.google.gerrit.reviewdb.Project;
import com.google.gerrit.reviewdb.RefRight;
import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.Panel;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import com.google.gwtexpui.safehtml.client.SafeHtml;
import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder;
@@ -65,14 +52,7 @@ public class ProjectAccessScreen extends ProjectScreen {
private RightsTable rights;
private Button delRight;
private Button addRight;
private ListBox catBox;
private ListBox rangeMinBox;
private ListBox rangeMaxBox;
private NpTextBox nameTxtBox;
private SuggestBox nameTxt;
private NpTextBox referenceTxt;
private FlowPanel addPanel;
private AccessRightEditor rightEditor;
public ProjectAccessScreen(final Project.NameKey toShow) {
super(toShow);
@@ -99,14 +79,7 @@ public class ProjectAccessScreen extends ProjectScreen {
private void enableForm(final boolean on) {
delRight.setEnabled(on);
final boolean canAdd = on && catBox.getItemCount() > 0;
addRight.setEnabled(canAdd);
nameTxtBox.setEnabled(canAdd);
referenceTxt.setEnabled(canAdd);
catBox.setEnabled(canAdd);
rangeMinBox.setEnabled(canAdd);
rangeMaxBox.setEnabled(canAdd);
rightEditor.enableForm(on);
}
private void initParent() {
@@ -119,102 +92,6 @@ public class ProjectAccessScreen extends ProjectScreen {
}
private void initRights() {
addPanel = new FlowPanel();
addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel());
final Grid addGrid = new Grid(5, 2);
catBox = new ListBox();
rangeMinBox = new ListBox();
rangeMaxBox = new ListBox();
catBox.addChangeHandler(new ChangeHandler() {
@Override
public void onChange(final ChangeEvent event) {
updateCategorySelection();
}
});
for (final ApprovalType at : Gerrit.getConfig().getApprovalTypes()
.getApprovalTypes()) {
final ApprovalCategory c = at.getCategory();
catBox.addItem(c.getName(), c.getId().get());
}
for (final ApprovalType at : Gerrit.getConfig().getApprovalTypes()
.getActionTypes()) {
final ApprovalCategory c = at.getCategory();
if (Gerrit.getConfig().getWildProject().equals(getProjectKey())
&& ApprovalCategory.OWN.equals(c.getId())) {
// Giving out control of the WILD_PROJECT to other groups beyond
// Administrators is dangerous. Having control over WILD_PROJECT
// is about the same as having Administrator access as users are
// able to affect grants in all projects on the system.
//
continue;
}
catBox.addItem(c.getName(), c.getId().get());
}
addGrid.setText(0, 0, Util.C.columnApprovalCategory() + ":");
addGrid.setWidget(0, 1, catBox);
nameTxtBox = new NpTextBox();
nameTxt = new SuggestBox(new AccountGroupSuggestOracle(), nameTxtBox);
nameTxtBox.setVisibleLength(50);
nameTxtBox.setText(Util.C.defaultAccountGroupName());
nameTxtBox.addStyleName(Gerrit.RESOURCES.css().inputFieldTypeHint());
nameTxtBox.addFocusHandler(new FocusHandler() {
@Override
public void onFocus(FocusEvent event) {
if (Util.C.defaultAccountGroupName().equals(nameTxtBox.getText())) {
nameTxtBox.setText("");
nameTxtBox.removeStyleName(Gerrit.RESOURCES.css()
.inputFieldTypeHint());
}
}
});
nameTxtBox.addBlurHandler(new BlurHandler() {
@Override
public void onBlur(BlurEvent event) {
if ("".equals(nameTxtBox.getText())) {
nameTxtBox.setText(Util.C.defaultAccountGroupName());
nameTxtBox.addStyleName(Gerrit.RESOURCES.css().inputFieldTypeHint());
}
}
});
addGrid.setText(1, 0, Util.C.columnGroupName() + ":");
addGrid.setWidget(1, 1, nameTxt);
referenceTxt = new NpTextBox();
referenceTxt.setVisibleLength(50);
referenceTxt.setText("");
referenceTxt.addKeyPressHandler(new KeyPressHandler() {
@Override
public void onKeyPress(KeyPressEvent event) {
if (event.getCharCode() == KeyCodes.KEY_ENTER) {
doAddNewRight();
}
}
});
addGrid.setText(2, 0, Util.C.columnRefName() + ":");
addGrid.setWidget(2, 1, referenceTxt);
addGrid.setText(3, 0, Util.C.columnRightRange() + ":");
addGrid.setWidget(3, 1, rangeMinBox);
addGrid.setText(4, 0, "");
addGrid.setWidget(4, 1, rangeMaxBox);
addRight = new Button(Util.C.buttonAddProjectRight());
addRight.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
doAddNewRight();
}
});
addPanel.add(addGrid);
addPanel.add(addRight);
rights = new RightsTable();
delRight = new Button(Util.C.buttonDeleteGroupMembers());
@@ -226,15 +103,18 @@ public class ProjectAccessScreen extends ProjectScreen {
}
});
rightEditor = new AccessRightEditor(getProjectKey());
rightEditor.addValueChangeHandler(new ValueChangeHandler<ProjectDetail>() {
@Override
public void onValueChange(ValueChangeEvent<ProjectDetail> event) {
display(event.getValue());
}
});
add(new SmallHeading(Util.C.headingAccessRights()));
add(rights);
add(delRight);
add(addPanel);
if (catBox.getItemCount() > 0) {
catBox.setSelectedIndex(0);
updateCategorySelection();
}
add(rightEditor);
}
void display(final ProjectDetail result) {
@@ -253,7 +133,7 @@ public class ProjectAccessScreen extends ProjectScreen {
rights.display(result.groups, result.rights);
addPanel.setVisible(result.canModifyAccess);
rightEditor.setVisible(result.canModifyAccess);
delRight.setVisible(rights.getCanDelete());
}
@@ -270,144 +150,9 @@ public class ProjectAccessScreen extends ProjectScreen {
}
}
private void doAddNewRight() {
int idx = catBox.getSelectedIndex();
final ApprovalType at;
ApprovalCategoryValue min, max;
if (idx < 0) {
return;
}
at =
Gerrit.getConfig().getApprovalTypes().getApprovalType(
new ApprovalCategory.Id(catBox.getValue(idx)));
if (at == null) {
return;
}
idx = rangeMinBox.getSelectedIndex();
if (idx < 0) {
return;
}
min = at.getValue(Short.parseShort(rangeMinBox.getValue(idx)));
if (min == null) {
return;
}
if (at.getCategory().isRange()) {
idx = rangeMaxBox.getSelectedIndex();
if (idx < 0) {
return;
}
max = at.getValue(Short.parseShort(rangeMaxBox.getValue(idx)));
if (max == null) {
return;
}
} else {
// If its not a range, the maximum box was disabled. Use the min
// value as the max, and select the min from the category values.
//
max = min;
min = at.getMin();
for (ApprovalCategoryValue v : at.getValues()) {
if (0 <= v.getValue() && v.getValue() <= max.getValue()) {
min = v;
break;
}
}
}
final String groupName = nameTxt.getText();
if ("".equals(groupName)
|| Util.C.defaultAccountGroupName().equals(groupName)) {
return;
}
final String refPattern = referenceTxt.getText();
if (min.getValue() > max.getValue()) {
// If the user selects it backwards in the web UI, help them out
// by reversing the order to what we would expect.
//
final ApprovalCategoryValue newMin = max;
final ApprovalCategoryValue newMax = min;
min = newMin;
max = newMax;
}
addRight.setEnabled(false);
Util.PROJECT_SVC.addRight(getProjectKey(), at.getCategory().getId(),
groupName, refPattern, min.getValue(), max.getValue(),
new GerritCallback<ProjectDetail>() {
public void onSuccess(final ProjectDetail result) {
addRight.setEnabled(true);
nameTxt.setText("");
referenceTxt.setText("");
display(result);
}
@Override
public void onFailure(final Throwable caught) {
addRight.setEnabled(true);
super.onFailure(caught);
}
});
}
private void updateCategorySelection() {
final int idx = catBox.getSelectedIndex();
final ApprovalType at;
if (idx >= 0) {
at =
Gerrit.getConfig().getApprovalTypes().getApprovalType(
new ApprovalCategory.Id(catBox.getValue(idx)));
} else {
at = null;
}
if (at == null || at.getValues().isEmpty()) {
rangeMinBox.setEnabled(false);
rangeMaxBox.setEnabled(false);
referenceTxt.setEnabled(false);
addRight.setEnabled(false);
return;
}
int curIndex = 0, minIndex = -1, maxIndex = -1;
rangeMinBox.clear();
rangeMaxBox.clear();
for (final ApprovalCategoryValue v : at.getValues()) {
final String vStr = String.valueOf(v.getValue());
String nStr = vStr + ": " + v.getName();
if (v.getValue() > 0) {
nStr = "+" + nStr;
}
rangeMinBox.addItem(nStr, vStr);
rangeMaxBox.addItem(nStr, vStr);
if (v.getValue() < 0) {
minIndex = curIndex;
}
if (maxIndex < 0 && v.getValue() > 0) {
maxIndex = curIndex;
}
curIndex++;
}
if (ApprovalCategory.READ.equals(at.getCategory().getId())) {
// Special case; for READ the most logical range is just
// +1 READ, so assume that as the default for both.
minIndex = maxIndex;
}
rangeMinBox.setSelectedIndex(minIndex >= 0 ? minIndex : 0);
rangeMaxBox.setSelectedIndex(maxIndex >= 0 ? maxIndex : curIndex - 1);
rangeMaxBox.setVisible(at.getCategory().isRange());
addRight.setEnabled(true);
}
private class RightsTable extends FancyFlexTable<RefRight> {
boolean canDelete;
Map<AccountGroup.Id, AccountGroup> groups;
RightsTable() {
table.setWidth("");
@@ -422,6 +167,13 @@ public class ProjectAccessScreen extends ProjectScreen {
fmt.addStyleName(0, 3, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 4, Gerrit.RESOURCES.css().dataHeader());
fmt.addStyleName(0, 5, Gerrit.RESOURCES.css().dataHeader());
table.addClickHandler(new ClickHandler() {
@Override
public void onClick(final ClickEvent event) {
onOpenRow(table.getCellForEvent(event).getRowIndex());
}
});
}
HashSet<RefRight.Key> getRefRightIdsChecked() {
@@ -436,8 +188,9 @@ public class ProjectAccessScreen extends ProjectScreen {
return refRightIds;
}
void display(final Map<AccountGroup.Id, AccountGroup> groups,
void display(final Map<AccountGroup.Id, AccountGroup> grps,
final List<InheritedRefRight> refRights) {
groups = grps;
canDelete = false;
while (1 < table.getRowCount())
@@ -447,12 +200,17 @@ public class ProjectAccessScreen extends ProjectScreen {
final int row = table.getRowCount();
table.insertRow(row);
applyDataRowStyle(row);
populate(row, groups, r);
populate(row, r);
}
}
protected void onOpenRow(final int row) {
if (row > 0) {
RefRight right = getRowItem(row);
rightEditor.load(right, groups.get(right.getAccountGroupId()));
}
}
void populate(final int row, final Map<AccountGroup.Id, AccountGroup> groups,
final InheritedRefRight r) {
void populate(final int row, final InheritedRefRight r) {
final GerritConfig config = Gerrit.getConfig();
final RefRight right = r.getRight();
final ApprovalType ar =
@@ -467,11 +225,8 @@ public class ProjectAccessScreen extends ProjectScreen {
canDelete = true;
}
if (ar != null) {
table.setText(row, 2, ar.getCategory().getName());
} else {
table.setText(row, 2, right.getApprovalCategoryId().get());
}
table.setText(row, 2, ar != null ? ar.getCategory().getName()
: right.getApprovalCategoryId().get() );
if (group != null) {
table.setText(row, 3, group.getName());