Cleanup the style and layout for the SSH key tab in account settings
Checkboxes can now be used to delete multiple keys at once, as that UI is much easier to understand than using the cursor to move onto the row you want to delete. Signed-off-by: Shawn O. Pearce <sop@google.com>
This commit is contained in:
@@ -18,4 +18,23 @@ import com.google.gwt.i18n.client.Constants;
|
||||
|
||||
public interface AccountConstants extends Constants {
|
||||
String accountSettingsHeading();
|
||||
|
||||
String fullName();
|
||||
String preferredEmail();
|
||||
String registeredOn();
|
||||
|
||||
String tabPreferences();
|
||||
String tabSshKeys();
|
||||
String tabAgreements();
|
||||
|
||||
String buttonDeleteSshKey();
|
||||
String buttonAddSshKey();
|
||||
|
||||
String sshKeyAlgorithm();
|
||||
String sshKeyKey();
|
||||
String sshKeyComment();
|
||||
String sshKeyLastUsed();
|
||||
String sshKeyStored();
|
||||
|
||||
String addSshKeyPanelHeader();
|
||||
}
|
||||
|
||||
@@ -1 +1,20 @@
|
||||
accountSettingsHeading = Account Settings
|
||||
|
||||
fullName = Full Name
|
||||
preferredEmail = Email Address
|
||||
registeredOn = Registered
|
||||
|
||||
tabPreferences = Preferences
|
||||
tabSshKeys = SSH Keys
|
||||
tabAgreements = Agreements
|
||||
|
||||
buttonDeleteSshKey = Delete
|
||||
buttonAddSshKey = Add
|
||||
|
||||
sshKeyAlgorithm = Algorithm
|
||||
sshKeyKey = Key
|
||||
sshKeyComment = Comment
|
||||
sshKeyLastUsed = Last Used
|
||||
sshKeyStored = Stored
|
||||
|
||||
addSshKeyPanelHeader = Add SSH Key
|
||||
|
||||
@@ -21,16 +21,20 @@ 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 AccountService extends RemoteJsonService {
|
||||
@SignInRequired
|
||||
void myAccount(AsyncCallback<Account> callback);
|
||||
|
||||
@SignInRequired
|
||||
void mySshKeys(AsyncCallback<SshKeyList> callback);
|
||||
void mySshKeys(AsyncCallback<List<AccountSshKey>> callback);
|
||||
|
||||
@SignInRequired
|
||||
void addSshKey(String keyText, AsyncCallback<AccountSshKey> callback);
|
||||
|
||||
@SignInRequired
|
||||
void deleteSshKey(AccountSshKey.Id id, AsyncCallback<VoidResult> callback);
|
||||
void deleteSshKeys(Set<AccountSshKey.Id> ids,
|
||||
AsyncCallback<VoidResult> callback);
|
||||
}
|
||||
|
||||
@@ -24,8 +24,11 @@ import com.google.gwt.user.client.rpc.AsyncCallback;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
import com.google.gwtorm.client.OrmException;
|
||||
import com.google.gwtorm.client.SchemaFactory;
|
||||
import com.google.gwtorm.client.Transaction;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class AccountServiceImpl extends BaseServiceImplementation implements
|
||||
AccountService {
|
||||
@@ -41,11 +44,10 @@ public class AccountServiceImpl extends BaseServiceImplementation implements
|
||||
});
|
||||
}
|
||||
|
||||
public void mySshKeys(final AsyncCallback<SshKeyList> callback) {
|
||||
run(callback, new Action<SshKeyList>() {
|
||||
public SshKeyList run(ReviewDb db) throws OrmException {
|
||||
return new SshKeyList(db.accountSshKeys().byAccount(
|
||||
RpcUtil.getAccountId()).toList());
|
||||
public void mySshKeys(final AsyncCallback<List<AccountSshKey>> callback) {
|
||||
run(callback, new Action<List<AccountSshKey>>() {
|
||||
public List<AccountSshKey> run(ReviewDb db) throws OrmException {
|
||||
return db.accountSshKeys().byAccount(RpcUtil.getAccountId()).toList();
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -68,16 +70,22 @@ public class AccountServiceImpl extends BaseServiceImplementation implements
|
||||
});
|
||||
}
|
||||
|
||||
public void deleteSshKey(final AccountSshKey.Id id,
|
||||
public void deleteSshKeys(final Set<AccountSshKey.Id> ids,
|
||||
final AsyncCallback<VoidResult> callback) {
|
||||
run(callback, new Action<VoidResult>() {
|
||||
public VoidResult run(final ReviewDb db) throws OrmException, Failure {
|
||||
final Account.Id me = RpcUtil.getAccountId();
|
||||
if (!me.equals(id.getParentKey()))
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
for (final AccountSshKey.Id keyId : ids) {
|
||||
if (!me.equals(keyId.getParentKey()))
|
||||
throw new Failure(new NoSuchEntityException());
|
||||
}
|
||||
|
||||
final AccountSshKey k = db.accountSshKeys().get(id);
|
||||
if (k != null) db.accountSshKeys().delete(Collections.singleton(k));
|
||||
final List<AccountSshKey> k = db.accountSshKeys().get(ids).toList();
|
||||
if (!k.isEmpty()) {
|
||||
final Transaction txn = db.beginTransaction();
|
||||
db.accountSshKeys().delete(k, txn);
|
||||
txn.commit();
|
||||
}
|
||||
|
||||
return VoidResult.INSTANCE;
|
||||
}
|
||||
|
||||
@@ -40,11 +40,12 @@ public class AccountSettings extends AccountScreen {
|
||||
|
||||
info = new Grid(3, 2);
|
||||
info.setStyleName("gerrit-InfoBlock");
|
||||
info.addStyleName("gerrit-AccountInfoBlock");
|
||||
add(info);
|
||||
|
||||
infoRow(0, "Full Name");
|
||||
infoRow(1, "Email Address");
|
||||
infoRow(2, "Registered");
|
||||
infoRow(0, Util.C.fullName());
|
||||
infoRow(1, Util.C.preferredEmail());
|
||||
infoRow(2, Util.C.registeredOn());
|
||||
|
||||
final CellFormatter fmt = info.getCellFormatter();
|
||||
fmt.addStyleName(0, 0, "topmost");
|
||||
@@ -61,9 +62,9 @@ public class AccountSettings extends AccountScreen {
|
||||
|
||||
tabs = new TabPanel();
|
||||
tabs.setWidth("100%");
|
||||
tabs.add(prefsPanel, "Preferences");
|
||||
tabs.add(keysPanel, "SSH Keys");
|
||||
tabs.add(agreementsPanel, "Agreements");
|
||||
tabs.add(prefsPanel, Util.C.tabPreferences());
|
||||
tabs.add(keysPanel, Util.C.tabSshKeys());
|
||||
tabs.add(agreementsPanel, Util.C.tabAgreements());
|
||||
|
||||
add(tabs);
|
||||
tabs.selectTab(0);
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
// 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.account;
|
||||
|
||||
import com.google.gerrit.client.reviewdb.AccountSshKey;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
final class SshKeyList {
|
||||
List<AccountSshKey> keys;
|
||||
|
||||
protected SshKeyList() {
|
||||
}
|
||||
|
||||
public SshKeyList(final List<AccountSshKey> k) {
|
||||
keys = k;
|
||||
}
|
||||
}
|
||||
@@ -19,16 +19,20 @@ import com.google.gerrit.client.reviewdb.AccountSshKey;
|
||||
import com.google.gerrit.client.rpc.GerritCallback;
|
||||
import com.google.gerrit.client.ui.FancyFlexTable;
|
||||
import com.google.gwt.user.client.ui.Button;
|
||||
import com.google.gwt.user.client.ui.CheckBox;
|
||||
import com.google.gwt.user.client.ui.ClickListener;
|
||||
import com.google.gwt.user.client.ui.Composite;
|
||||
import com.google.gwt.user.client.ui.FlowPanel;
|
||||
import com.google.gwt.user.client.ui.Label;
|
||||
import com.google.gwt.user.client.ui.SourcesTableEvents;
|
||||
import com.google.gwt.user.client.ui.TableListener;
|
||||
import com.google.gwt.user.client.ui.TextArea;
|
||||
import com.google.gwt.user.client.ui.VerticalPanel;
|
||||
import com.google.gwt.user.client.ui.Widget;
|
||||
import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
|
||||
import com.google.gwtjsonrpc.client.VoidResult;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
public class SshKeyPanel extends Composite {
|
||||
@@ -45,11 +49,10 @@ public class SshKeyPanel extends Composite {
|
||||
body.add(keys);
|
||||
{
|
||||
final FlowPanel fp = new FlowPanel();
|
||||
delSel = new Button("Delete");
|
||||
delSel.setEnabled(false);
|
||||
delSel = new Button(Util.C.buttonDeleteSshKey());
|
||||
delSel.addClickListener(new ClickListener() {
|
||||
public void onClick(final Widget sender) {
|
||||
keys.deleteCurrent();
|
||||
keys.deleteChecked();
|
||||
}
|
||||
});
|
||||
fp.add(delSel);
|
||||
@@ -57,13 +60,16 @@ public class SshKeyPanel extends Composite {
|
||||
}
|
||||
|
||||
{
|
||||
final FlowPanel fp = new FlowPanel();
|
||||
final VerticalPanel fp = new VerticalPanel();
|
||||
fp.setStyleName("gerrit-AddSshKeyPanel");
|
||||
fp.add(new Label(Util.C.addSshKeyPanelHeader()));
|
||||
|
||||
addTxt = new TextArea();
|
||||
addTxt.setVisibleLines(3);
|
||||
addTxt.setCharacterWidth(60);
|
||||
addTxt.setVisibleLines(12);
|
||||
addTxt.setCharacterWidth(80);
|
||||
fp.add(addTxt);
|
||||
|
||||
addNew = new Button("Add ...");
|
||||
addNew = new Button(Util.C.buttonAddSshKey());
|
||||
addNew.addClickListener(new ClickListener() {
|
||||
public void onClick(final Widget sender) {
|
||||
doAddNew();
|
||||
@@ -105,9 +111,9 @@ public class SshKeyPanel extends Composite {
|
||||
}
|
||||
|
||||
public void update() {
|
||||
Util.ACCOUNT_SVC.mySshKeys(new GerritCallback<SshKeyList>() {
|
||||
public void onSuccess(final SshKeyList result) {
|
||||
keys.display(result.keys);
|
||||
Util.ACCOUNT_SVC.mySshKeys(new GerritCallback<List<AccountSshKey>>() {
|
||||
public void onSuccess(final List<AccountSshKey> result) {
|
||||
keys.display(result);
|
||||
keys.finishDisplay(true);
|
||||
}
|
||||
});
|
||||
@@ -115,36 +121,26 @@ public class SshKeyPanel extends Composite {
|
||||
|
||||
private class SshKeyTable extends FancyFlexTable<AccountSshKey> {
|
||||
SshKeyTable() {
|
||||
table.setText(0, 1, "Algorithm");
|
||||
table.setText(0, 2, "Key");
|
||||
table.setText(0, 3, "Comment");
|
||||
table.setText(0, 4, "Last Used");
|
||||
table.setText(0, 5, "Stored");
|
||||
table.setText(0, 2, Util.C.sshKeyAlgorithm());
|
||||
table.setText(0, 3, Util.C.sshKeyKey());
|
||||
table.setText(0, 4, Util.C.sshKeyComment());
|
||||
table.setText(0, 5, Util.C.sshKeyLastUsed());
|
||||
table.setText(0, 6, Util.C.sshKeyStored());
|
||||
table.addTableListener(new TableListener() {
|
||||
public void onCellClicked(SourcesTableEvents sender, int row, int cell) {
|
||||
if (getRowItem(row) != null) {
|
||||
if (cell != 1 && getRowItem(row) != null) {
|
||||
movePointerTo(row);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||
fmt.addStyleName(0, 1, S_DATA_HEADER);
|
||||
fmt.addStyleName(0, 1, S_ICON_HEADER);
|
||||
fmt.addStyleName(0, 2, S_DATA_HEADER);
|
||||
fmt.addStyleName(0, 3, S_DATA_HEADER);
|
||||
fmt.addStyleName(0, 4, S_DATA_HEADER);
|
||||
fmt.addStyleName(0, 5, S_DATA_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void movePointerTo(final int newRow) {
|
||||
super.movePointerTo(newRow);
|
||||
if (0 <= newRow && newRow < table.getRowCount()
|
||||
&& getRowItem(newRow) != null) {
|
||||
delSel.setEnabled(true);
|
||||
} else {
|
||||
delSel.setEnabled(false);
|
||||
}
|
||||
fmt.addStyleName(0, 6, S_DATA_HEADER);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -152,28 +148,54 @@ public class SshKeyPanel extends Composite {
|
||||
return item.getKey();
|
||||
}
|
||||
|
||||
void deleteCurrent() {
|
||||
final int row = getCurrentRow();
|
||||
if (0 <= row && row < table.getRowCount()) {
|
||||
final AccountSshKey k = getRowItem(row);
|
||||
if (k != null) {
|
||||
Util.ACCOUNT_SVC.deleteSshKey(k.getKey(),
|
||||
new GerritCallback<VoidResult>() {
|
||||
public void onSuccess(final VoidResult result) {
|
||||
int jumpTo = -1;
|
||||
for (int i = 0; i < table.getRowCount(); i++) {
|
||||
if (getRowItem(i) == k) {
|
||||
table.removeRow(i);
|
||||
movePointerTo(jumpTo);
|
||||
break;
|
||||
} else if (getRowItem(i) != null) {
|
||||
jumpTo = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@Override
|
||||
protected boolean onKeyPress(final char keyCode, final int modifiers) {
|
||||
if (super.onKeyPress(keyCode, modifiers)) {
|
||||
return true;
|
||||
}
|
||||
if (modifiers == 0) {
|
||||
switch (keyCode) {
|
||||
case 's':
|
||||
case 'c':
|
||||
toggleCurrentRow();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onOpenItem(final AccountSshKey item) {
|
||||
toggleCurrentRow();
|
||||
}
|
||||
|
||||
private void toggleCurrentRow() {
|
||||
final CheckBox cb = (CheckBox) table.getWidget(getCurrentRow(), 1);
|
||||
cb.setChecked(!cb.isChecked());
|
||||
}
|
||||
|
||||
void deleteChecked() {
|
||||
final HashSet<AccountSshKey.Id> ids = new HashSet<AccountSshKey.Id>();
|
||||
for (int row = 1; row < table.getRowCount(); row++) {
|
||||
final AccountSshKey k = getRowItem(row);
|
||||
if (k != null && ((CheckBox) table.getWidget(row, 1)).isChecked()) {
|
||||
ids.add(k.getKey());
|
||||
}
|
||||
}
|
||||
if (!ids.isEmpty()) {
|
||||
Util.ACCOUNT_SVC.deleteSshKeys(ids, new GerritCallback<VoidResult>() {
|
||||
public void onSuccess(final VoidResult result) {
|
||||
for (int row = 1; row < table.getRowCount();) {
|
||||
final AccountSshKey k = getRowItem(row);
|
||||
if (k != null && ids.contains(k.getKey())) {
|
||||
table.removeRow(row);
|
||||
} else {
|
||||
row++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void display(final List<AccountSshKey> result) {
|
||||
@@ -189,14 +211,19 @@ public class SshKeyPanel extends Composite {
|
||||
final int row = table.getRowCount();
|
||||
table.insertRow(row);
|
||||
|
||||
table.setText(row, 1, k.getAlgorithm());
|
||||
table.setText(row, 2, elide(k.getEncodedKey()));
|
||||
table.setText(row, 3, k.getComment());
|
||||
table.setText(row, 4, FormatUtil.mediumFormat(k.getLastUsedOn()));
|
||||
table.setText(row, 5, FormatUtil.mediumFormat(k.getStoredOn()));
|
||||
table.setWidget(row, 1, new CheckBox());
|
||||
table.setText(row, 2, k.getAlgorithm());
|
||||
table.setText(row, 3, elide(k.getEncodedKey()));
|
||||
table.setText(row, 4, k.getComment());
|
||||
table.setText(row, 5, FormatUtil.mediumFormat(k.getLastUsedOn()));
|
||||
table.setText(row, 6, FormatUtil.mediumFormat(k.getStoredOn()));
|
||||
|
||||
final FlexCellFormatter fmt = table.getFlexCellFormatter();
|
||||
fmt.addStyleName(row, 2, "gerrit-SshKeyPanel-EncodedKey");
|
||||
fmt.addStyleName(row, 1, S_ICON_CELL);
|
||||
fmt.addStyleName(row, 3, "gerrit-SshKeyPanel-EncodedKey");
|
||||
for (int c = 2; c <= 6; c++) {
|
||||
fmt.addStyleName(row, c, S_DATA_CELL);
|
||||
}
|
||||
|
||||
setRowItem(row, k);
|
||||
}
|
||||
|
||||
@@ -482,3 +482,16 @@
|
||||
overflow: hidden;
|
||||
font-family: Courier New, Courier, monospace;
|
||||
}
|
||||
|
||||
.gerrit-AccountInfoBlock {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.gerrit-AddSshKeyPanel {
|
||||
margin-top: 10px;
|
||||
background-color: #d4e9a9;
|
||||
padding: 5px 5px 5px 5px;
|
||||
}
|
||||
.gerrit-AddSshKeyPanel .gwt-Label {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user