From 04c3458834ada6cdf5a4a0fd47f30fa9a414bc83 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Jul 2010 17:38:51 -0700 Subject: [PATCH 1/9] Remove unused import in SshPanel Change-Id: I8e32f3137fefb9b04dffa28ea14f6bd399190803 Signed-off-by: Shawn O. Pearce --- .../src/main/java/com/google/gerrit/client/account/SshPanel.java | 1 - 1 file changed, 1 deletion(-) diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java index 50f0d42d0f..3bf1497bca 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java @@ -37,7 +37,6 @@ import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HasHorizontalAlignment; import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwt.user.client.ui.InlineLabel; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.RootPanel; import com.google.gwt.user.client.ui.VerticalPanel; From dabf1acee4ad6148b7d1020f7d18ae571f039f65 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Jul 2010 17:37:21 -0700 Subject: [PATCH 2/9] Copy the full SSH key to the clipboard When using the copy-to-clipboard feature for an SSH key, copy the entire key string so its a valid input for the OpenSSH authorized keys file. Change-Id: I6b313d05ff31a046eb2a87fd13282a8a838018cd Signed-off-by: Shawn O. Pearce --- .../main/java/com/google/gerrit/client/account/SshPanel.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java index 3bf1497bca..014e514228 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java @@ -439,7 +439,7 @@ class SshPanel extends Composite { } table.setText(row, 3, k.getAlgorithm()); - CopyableLabel keyLabel = new CopyableLabel(k.getEncodedKey()); + CopyableLabel keyLabel = new CopyableLabel(k.getSshPublicKey()); keyLabel.setPreviewText(elide(k.getEncodedKey(), 40)); table.setWidget(row, 4, keyLabel); From 8840552f5fb1baff243f85a2acf409f879b1a25c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Jul 2010 17:57:58 -0700 Subject: [PATCH 3/9] Stop allowing password authentication over SSH For a service like Gerrit Code Review, it just doesn't make much sense to offer password authentication for users. Anyone who sets up an account with us can configure an SSH key and use that for login. Change-Id: I93373e0a69a7d9adf48001d58983dc8233dcf22e Signed-off-by: Shawn O. Pearce --- .../gerrit/sshd/DatabasePasswordAuth.java | 116 ------------------ .../com/google/gerrit/sshd/SshDaemon.java | 13 +- .../com/google/gerrit/sshd/SshModule.java | 3 - 3 files changed, 4 insertions(+), 128 deletions(-) delete mode 100644 gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePasswordAuth.java diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePasswordAuth.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePasswordAuth.java deleted file mode 100644 index a346ab6087..0000000000 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DatabasePasswordAuth.java +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (C) 2010 The Android Open Source Project -// -// 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.sshd; - -import com.google.gerrit.reviewdb.AccountExternalId; -import com.google.gerrit.server.AccessPath; -import com.google.gerrit.server.IdentifiedUser; -import com.google.gerrit.server.account.AccountCache; -import com.google.gerrit.server.account.AccountState; -import com.google.gerrit.sshd.SshScope.Context; -import com.google.inject.Inject; -import com.google.inject.Provider; -import com.google.inject.Singleton; - -import org.apache.mina.core.future.IoFuture; -import org.apache.mina.core.future.IoFutureListener; -import org.apache.sshd.server.PasswordAuthenticator; -import org.apache.sshd.server.session.ServerSession; - -import java.net.SocketAddress; - -/** - * Authenticates by password through {@link AccountExternalId} entities. - */ -@Singleton -class DatabasePasswordAuth implements PasswordAuthenticator { - private final AccountCache accountCache; - private final SshLog log; - private final IdentifiedUser.GenericFactory userFactory; - - @Inject - DatabasePasswordAuth(final AccountCache ac, final SshLog l, - final IdentifiedUser.GenericFactory uf) { - accountCache = ac; - log = l; - userFactory = uf; - } - - @Override - public boolean authenticate(final String username, final String password, - final ServerSession session) { - final SshSession sd = session.getAttribute(SshSession.KEY); - - AccountState state = accountCache.getByUsername(username); - if (state == null) { - sd.authenticationError(username, "user-not-found"); - return false; - } - - final String p = state.getPassword(username); - if (p == null) { - sd.authenticationError(username, "no-password"); - return false; - } - - if (!p.equals(password)) { - sd.authenticationError(username, "incorrect-password"); - return false; - } - - if (sd.getCurrentUser() == null) { - sd.authenticationSuccess(username, createUser(sd, state)); - - // If this is the first time we've authenticated this - // session, record a login event in the log and add - // a close listener to record a logout event. - // - Context ctx = new Context(sd, null); - Context old = SshScope.set(ctx); - try { - log.onLogin(); - } finally { - SshScope.set(old); - } - - session.getIoSession().getCloseFuture().addListener( - new IoFutureListener() { - @Override - public void operationComplete(IoFuture future) { - final Context ctx = new Context(sd, null); - final Context old = SshScope.set(ctx); - try { - log.onLogout(); - } finally { - SshScope.set(old); - } - } - }); - } - - return true; - } - - private IdentifiedUser createUser(final SshSession sd, - final AccountState state) { - return userFactory.create(AccessPath.SSH_COMMAND, - new Provider() { - @Override - public SocketAddress get() { - return sd.getRemoteAddress(); - } - }, state.getAccount().getId()); - } -} diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java index 35fd229c0f..2636ff2597 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java @@ -59,10 +59,8 @@ import org.apache.sshd.common.util.SecurityUtils; import org.apache.sshd.server.Command; import org.apache.sshd.server.CommandFactory; import org.apache.sshd.server.ForwardingFilter; -import org.apache.sshd.server.PasswordAuthenticator; import org.apache.sshd.server.PublickeyAuthenticator; import org.apache.sshd.server.UserAuth; -import org.apache.sshd.server.auth.UserAuthPassword; import org.apache.sshd.server.auth.UserAuthPublicKey; import org.apache.sshd.server.channel.ChannelDirectTcpip; import org.apache.sshd.server.channel.ChannelSession; @@ -119,7 +117,6 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener { @Inject SshDaemon(final CommandFactory commandFactory, - final PasswordAuthenticator passAuth, final PublickeyAuthenticator userAuth, final KeyPairProvider hostKeyProvider, final IdGenerator idGenerator, @GerritServerConfig final Config cfg, final SshLog sshLog) { @@ -141,7 +138,7 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener { initForwardingFilter(); initSubsystems(); initCompression(); - initUserAuth(passAuth, userAuth); + initUserAuth(userAuth); setKeyPairProvider(hostKeyProvider); setCommandFactory(commandFactory); setShellFactory(new NoShell()); @@ -459,11 +456,9 @@ public class SshDaemon extends SshServer implements SshInfo, LifecycleListener { } @SuppressWarnings("unchecked") - private void initUserAuth(final PasswordAuthenticator pass, - final PublickeyAuthenticator pubkey) { - setUserAuthFactories(Arrays.> asList( - new UserAuthPublicKey.Factory(), new UserAuthPassword.Factory())); - setPasswordAuthenticator(pass); + private void initUserAuth(final PublickeyAuthenticator pubkey) { + setUserAuthFactories(Arrays + .> asList(new UserAuthPublicKey.Factory())); setPublickeyAuthenticator(pubkey); } diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java index 15fc093e76..40d271b975 100644 --- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java +++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java @@ -40,14 +40,12 @@ import com.google.gerrit.util.cli.CmdLineParser; import com.google.gerrit.util.cli.OptionHandlerFactory; import com.google.gerrit.util.cli.OptionHandlerUtil; import com.google.inject.Key; -import com.google.inject.Scopes; import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryProvider; import com.google.inject.servlet.RequestScoped; import org.apache.sshd.common.KeyPairProvider; import org.apache.sshd.server.CommandFactory; -import org.apache.sshd.server.PasswordAuthenticator; import org.apache.sshd.server.PublickeyAuthenticator; import org.kohsuke.args4j.spi.OptionHandler; @@ -78,7 +76,6 @@ public class SshModule extends FactoryModule { bind(QueueProvider.class).to(CommandExecutorQueueProvider.class).in(SINGLETON); bind(PublickeyAuthenticator.class).to(DatabasePubKeyAuth.class); - bind(PasswordAuthenticator.class).to(DatabasePasswordAuth.class); bind(KeyPairProvider.class).toProvider(HostKeyProvider.class).in(SINGLETON); bind(TransferConfig.class); From 2005988c41f700d8dd9c2e9f4c01827a3e01a71c Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Jul 2010 18:24:17 -0700 Subject: [PATCH 4/9] Add username to the Account Settings information block Change-Id: Iad97c44c576505748b7dfd647253044591d668cf Signed-off-by: Shawn O. Pearce --- .../client/account/AccountSettings.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountSettings.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountSettings.java index 59a754729c..d6d99dde5e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountSettings.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountSettings.java @@ -78,20 +78,21 @@ public class AccountSettings extends AccountScreen { fieldIdx = 1; } - info = new Grid(4, 2); + info = new Grid(5, 2); info.setStyleName(Gerrit.RESOURCES.css().infoBlock()); info.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock()); add(info); - infoRow(0, Util.C.fullName()); - infoRow(1, Util.C.preferredEmail()); - infoRow(2, Util.C.registeredOn()); - infoRow(3, Util.C.accountId()); + infoRow(0, Util.C.userName()); + infoRow(1, Util.C.fullName()); + infoRow(2, Util.C.preferredEmail()); + infoRow(3, Util.C.registeredOn()); + infoRow(4, Util.C.accountId()); final CellFormatter fmt = info.getCellFormatter(); fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); - fmt.addStyleName(3, 0, Gerrit.RESOURCES.css().bottomheader()); + fmt.addStyleName(4, 0, Gerrit.RESOURCES.css().bottomheader()); tabTokens = new ArrayList(); tabs = new TabPanel(); @@ -173,9 +174,10 @@ public class AccountSettings extends AccountScreen { } void display(final Account account) { - info.setText(0, fieldIdx, account.getFullName()); - info.setText(1, fieldIdx, account.getPreferredEmail()); - info.setText(2, fieldIdx, mediumFormat(account.getRegisteredOn())); - info.setText(3, fieldIdx, account.getId().toString()); + info.setText(0, fieldIdx, account.getUserName()); + info.setText(1, fieldIdx, account.getFullName()); + info.setText(2, fieldIdx, account.getPreferredEmail()); + info.setText(3, fieldIdx, mediumFormat(account.getRegisteredOn())); + info.setText(4, fieldIdx, account.getId().toString()); } } From 14bedca306430336156894cb463ff493df32244f Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Jul 2010 19:37:40 -0700 Subject: [PATCH 5/9] Fix loading AccountResources and its key_applet in hosted mode We need the Maven generated classes directory on our classpath, otherwise the keyapplet_jar text resource isn't available. Change-Id: Ic68ce1dd80816f2a288fd830f7dfa4db3157a8c2 Signed-off-by: Shawn O. Pearce --- tools/gwtui_dbg.launch | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gwtui_dbg.launch b/tools/gwtui_dbg.launch index a5949a851a..58f5ec8c55 100644 --- a/tools/gwtui_dbg.launch +++ b/tools/gwtui_dbg.launch @@ -24,6 +24,7 @@ + From 270c5941d41db707ce8d5ca3f2504b7d498795a1 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 14 Jul 2010 20:22:22 -0700 Subject: [PATCH 6/9] Move project and settings tabs to left side Instead of using a GWT TabPanel to show the project and settings tabs, move them onto the left as part of a vertically stacked menu. This just looks cleaner, and helps us to avoid ultra wide windows in the settings area as the number of tabs keeps increasing. While we are doing the UI refactoring, make each section proper top level screen objects. This makes it far easier to ensure the data is loaded in the background before the UI gets displayed, which removes some of the display jitter you see as you navigate to a section. This also nicely fixes some table UI layout glitches that were caused by the TabPanel forcing our content width to 100% even though we didn't want that. Change-Id: I5da0dadddc2746206852a0873d6014051bd9f6dc Signed-off-by: Shawn O. Pearce --- .../com/google/gerrit/common/PageLinks.java | 1 + .../com/google/gerrit/client/Dispatcher.java | 81 +++++++- .../com/google/gerrit/client/GerritCss.java | 1 + .../client/account/AccountConstants.java | 5 +- .../account/AccountConstants.properties | 7 +- .../client/account/AccountSettings.java | 183 ------------------ .../client/account/ContactPanelShort.java | 9 +- ...mentPanel.java => MyAgreementsScreen.java} | 21 +- .../account/MyContactInformationScreen.java | 31 +++ ...MyGroupsPanel.java => MyGroupsScreen.java} | 24 +-- ...alIdPanel.java => MyIdentitiesScreen.java} | 26 ++- ...ncePanel.java => MyPreferencesScreen.java} | 21 +- .../client/account/MyProfileScreen.java | 78 ++++++++ .../client/account/MySshKeysScreen.java | 31 +++ ...anel.java => MyWatchedProjectsScreen.java} | 22 +-- .../gerrit/client/account/SettingsScreen.java | 42 ++++ .../gerrit/client/account/SshPanel.java | 12 +- .../client/account/ValidateEmailScreen.java | 2 +- ...htsPanel.java => ProjectAccessScreen.java} | 57 +++--- .../client/admin/ProjectAdminScreen.java | 119 ------------ ...sPanel.java => ProjectBranchesScreen.java} | 44 ++--- ...tInfoPanel.java => ProjectInfoScreen.java} | 57 +++--- .../client/admin/ProjectListScreen.java | 2 +- .../gerrit/client/admin/ProjectScreen.java | 39 ++++ .../java/com/google/gerrit/client/gerrit.css | 23 +++ .../google/gerrit/client/ui/LinkMenuBar.java | 12 ++ .../google/gerrit/client/ui/MenuScreen.java | 61 ++++++ .../com/google/gerrit/client/ui/Screen.java | 2 +- 28 files changed, 534 insertions(+), 479 deletions(-) delete mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountSettings.java rename gerrit-gwtui/src/main/java/com/google/gerrit/client/account/{AgreementPanel.java => MyAgreementsScreen.java} (89%) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java rename gerrit-gwtui/src/main/java/com/google/gerrit/client/account/{MyGroupsPanel.java => MyGroupsScreen.java} (67%) rename gerrit-gwtui/src/main/java/com/google/gerrit/client/account/{ExternalIdPanel.java => MyIdentitiesScreen.java} (94%) rename gerrit-gwtui/src/main/java/com/google/gerrit/client/account/{PreferencePanel.java => MyPreferencesScreen.java} (93%) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java rename gerrit-gwtui/src/main/java/com/google/gerrit/client/account/{ProjectWatchPanel.java => MyWatchedProjectsScreen.java} (96%) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java rename gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/{ProjectRightsPanel.java => ProjectAccessScreen.java} (93%) delete mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java rename gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/{ProjectBranchesPanel.java => ProjectBranchesScreen.java} (93%) rename gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/{ProjectInfoPanel.java => ProjectInfoScreen.java} (85%) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java index 33295bca13..a502b3b100 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java @@ -24,6 +24,7 @@ import com.google.gwtorm.client.KeyUtil; public class PageLinks { public static final String SETTINGS = "settings"; + public static final String SETTINGS_PREFERENCES = "settings,preferences"; public static final String SETTINGS_SSHKEYS = "settings,ssh-keys"; public static final String SETTINGS_WEBIDENT = "settings,web-identities"; public static final String SETTINGS_MYGROUPS = "settings,group-memberships"; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java index de2f084723..a5cd9df39b 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java @@ -21,25 +21,40 @@ import static com.google.gerrit.common.PageLinks.MINE_DRAFTS; import static com.google.gerrit.common.PageLinks.MINE_STARRED; import static com.google.gerrit.common.PageLinks.REGISTER; import static com.google.gerrit.common.PageLinks.SETTINGS; +import static com.google.gerrit.common.PageLinks.SETTINGS_AGREEMENTS; +import static com.google.gerrit.common.PageLinks.SETTINGS_CONTACT; +import static com.google.gerrit.common.PageLinks.SETTINGS_MYGROUPS; import static com.google.gerrit.common.PageLinks.SETTINGS_NEW_AGREEMENT; +import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES; +import static com.google.gerrit.common.PageLinks.SETTINGS_PROJECTS; +import static com.google.gerrit.common.PageLinks.SETTINGS_SSHKEYS; import static com.google.gerrit.common.PageLinks.SETTINGS_WEBIDENT; import static com.google.gerrit.common.PageLinks.TOP; -import com.google.gerrit.client.account.AccountSettings; +import com.google.gerrit.client.account.MyAgreementsScreen; +import com.google.gerrit.client.account.MyContactInformationScreen; +import com.google.gerrit.client.account.MyGroupsScreen; +import com.google.gerrit.client.account.MyIdentitiesScreen; +import com.google.gerrit.client.account.MyPreferencesScreen; +import com.google.gerrit.client.account.MyProfileScreen; +import com.google.gerrit.client.account.MySshKeysScreen; +import com.google.gerrit.client.account.MyWatchedProjectsScreen; import com.google.gerrit.client.account.NewAgreementScreen; import com.google.gerrit.client.account.RegisterScreen; import com.google.gerrit.client.account.ValidateEmailScreen; import com.google.gerrit.client.admin.AccountGroupScreen; import com.google.gerrit.client.admin.GroupListScreen; -import com.google.gerrit.client.admin.ProjectAdminScreen; +import com.google.gerrit.client.admin.ProjectAccessScreen; +import com.google.gerrit.client.admin.ProjectBranchesScreen; +import com.google.gerrit.client.admin.ProjectInfoScreen; import com.google.gerrit.client.admin.ProjectListScreen; +import com.google.gerrit.client.admin.ProjectScreen; import com.google.gerrit.client.auth.openid.OpenIdSignInDialog; import com.google.gerrit.client.auth.userpass.UserPassSignInDialog; import com.google.gerrit.client.changes.AccountDashboardScreen; import com.google.gerrit.client.changes.AllAbandonedChangesScreen; import com.google.gerrit.client.changes.AllMergedChangesScreen; import com.google.gerrit.client.changes.AllOpenChangesScreen; -import com.google.gerrit.client.changes.MineWatchedOpenChangesScreen; import com.google.gerrit.client.changes.ByProjectAbandonedChangesScreen; import com.google.gerrit.client.changes.ByProjectMergedChangesScreen; import com.google.gerrit.client.changes.ByProjectOpenChangesScreen; @@ -47,11 +62,11 @@ import com.google.gerrit.client.changes.ChangeQueryResultsScreen; 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.MineWatchedOpenChangesScreen; import com.google.gerrit.client.changes.PatchTable; import com.google.gerrit.client.changes.PublishCommentScreen; import com.google.gerrit.client.patches.PatchScreen; import com.google.gerrit.client.ui.Screen; -import com.google.gerrit.common.PageLinks; import com.google.gerrit.common.auth.SignInMode; import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.AccountGroup; @@ -292,6 +307,39 @@ public class Dispatcher { private Screen select() { String p; + if (token.equals(SETTINGS)) { + return new MyProfileScreen(); + } + + if (token.equals(SETTINGS_PREFERENCES)) { + return new MyPreferencesScreen(); + } + + if (token.equals(SETTINGS_PROJECTS)) { + return new MyWatchedProjectsScreen(); + } + + if (token.equals(SETTINGS_CONTACT)) { + return new MyContactInformationScreen(); + } + + if (token.equals(SETTINGS_SSHKEYS)) { + return new MySshKeysScreen(); + } + + if (token.equals(SETTINGS_WEBIDENT)) { + return new MyIdentitiesScreen(); + } + + if (token.equals(SETTINGS_MYGROUPS)) { + return new MyGroupsScreen(); + } + + if (token.equals(SETTINGS_AGREEMENTS) + && Gerrit.getConfig().isUseContributorAgreements()) { + return new MyAgreementsScreen(); + } + p = "register,"; if (token.startsWith(p)) { return new RegisterScreen(skip(p, token)); @@ -308,7 +356,7 @@ public class Dispatcher { final String[] args = skip(p, token).split(","); final SignInMode mode = SignInMode.valueOf(args[0]); final String msg = KeyUtil.decode(args[1]); - final String to = PageLinks.MINE; + final String to = MINE; switch (Gerrit.getConfig().getAuthType()) { case OPENID: new OpenIdSignInDialog(mode, to, msg).center(); @@ -324,7 +372,7 @@ public class Dispatcher { case SIGN_IN: return new AllOpenChangesScreen(TOP); case LINK_IDENTIY: - return new AccountSettings(SETTINGS_WEBIDENT); + return new MyIdentitiesScreen(); } } @@ -336,7 +384,7 @@ public class Dispatcher { return new NewAgreementScreen(skip(p, token)); } - return new AccountSettings(token); + return new NotFoundScreen(); } }); } @@ -358,8 +406,23 @@ public class Dispatcher { if (token.startsWith(p)) { p = skip(p, token); final int c = p.indexOf(','); - final String idstr = p.substring(0, c); - return new ProjectAdminScreen(Project.NameKey.parse(idstr), token); + final Project.NameKey k = Project.NameKey.parse(p.substring(0, c)); + final boolean isWild = k.equals(Gerrit.getConfig().getWildProject()); + p = p.substring(c + 1); + + if (ProjectScreen.INFO.equals(p)) { + return new ProjectInfoScreen(k); + } + + if (!isWild && ProjectScreen.BRANCH.equals(p)) { + return new ProjectBranchesScreen(k); + } + + if (ProjectScreen.ACCESS.equals(p)) { + return new ProjectAccessScreen(k); + } + + return new NotFoundScreen(); } if (ADMIN_GROUPS.equals(token)) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java index 2d631ef9fb..8cea4b693e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java @@ -123,6 +123,7 @@ public interface GerritCss extends CssResource { String linkMenuItemNotLast(); String menuBarUserName(); String menuItem(); + String menuScreenMenuBar(); String missingApproval(); String missingApprovalList(); String needsReview(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java index bc93034322..fd5e030c91 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java @@ -17,7 +17,7 @@ package com.google.gerrit.client.account; import com.google.gwt.i18n.client.Constants; public interface AccountConstants extends Constants { - String accountSettingsHeading(); + String settingsHeading(); String fullName(); String preferredEmail(); @@ -31,7 +31,9 @@ public interface AccountConstants extends Constants { String copySelfOnEmails(); String buttonSaveChanges(); + String tabAccountSummary(); String tabPreferences(); + String tabWatchedProjects(); String tabContactInformation(); String tabSshKeys(); String tabWebIdentities(); @@ -73,7 +75,6 @@ public interface AccountConstants extends Constants { String buttonDeleteIdentity(); String buttonLinkIdentity(); - String watchedProjects(); String buttonWatchProject(); String defaultProjectName(); String watchedProjectColumnEmailNotifications(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties index b3a9fecfb9..b8cdd076f6 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties @@ -1,4 +1,4 @@ -accountSettingsHeading = Account Settings +settingsHeading = Settings fullName = Full Name preferredEmail = Email Address @@ -12,9 +12,11 @@ maximumPageSizeFieldLabel = Maximum Page Size: contextWholeFile = Whole File buttonSaveChanges = Save Changes +tabAccountSummary = Profile tabPreferences = Preferences +tabWatchedProjects = Watched Projects tabContactInformation = Contact Information -tabSshKeys = SSH Keys +tabSshKeys = SSH Public Keys tabWebIdentities = Identities tabMyGroups = Groups tabAgreements = Agreements @@ -54,7 +56,6 @@ addSshKeyHelp = ( tabTokens; - private TabPanel tabs; - - public AccountSettings(final String tabToken) { - initialTabToken = tabToken; - } - - @Override - public boolean displayToken(String token) { - final int tabIdx = tabTokens.indexOf(token); - if (0 <= tabIdx) { - tabs.selectTab(tabIdx); - setToken(token); - return true; - } else { - return false; - } - } - - @Override - protected void onLoad() { - super.onLoad(); - - final int idx = tabTokens.indexOf(initialTabToken); - tabs.selectTab(0 <= idx ? idx : 0); - display(Gerrit.getUserAccount()); - display(); - } - - @Override - protected void onInitUI() { - super.onInitUI(); - setPageTitle(Util.C.accountSettingsHeading()); - - if (LocaleInfo.getCurrentLocale().isRTL()) { - labelIdx = 1; - fieldIdx = 0; - } else { - labelIdx = 0; - fieldIdx = 1; - } - - info = new Grid(5, 2); - info.setStyleName(Gerrit.RESOURCES.css().infoBlock()); - info.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock()); - add(info); - - infoRow(0, Util.C.userName()); - infoRow(1, Util.C.fullName()); - infoRow(2, Util.C.preferredEmail()); - infoRow(3, Util.C.registeredOn()); - infoRow(4, Util.C.accountId()); - - final CellFormatter fmt = info.getCellFormatter(); - fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); - fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); - fmt.addStyleName(4, 0, Gerrit.RESOURCES.css().bottomheader()); - - tabTokens = new ArrayList(); - tabs = new TabPanel(); - tabs.setWidth("98%"); - add(tabs); - - tabs.add(new LazyPanel() { - @Override - protected PreferencePanel createWidget() { - return new PreferencePanel(); - } - }, Util.C.tabPreferences()); - tabTokens.add(PageLinks.SETTINGS); - - tabs.add(new LazyPanel() { - @Override - protected ProjectWatchPanel createWidget() { - return new ProjectWatchPanel(); - } - }, Util.C.watchedProjects()); - tabTokens.add(PageLinks.SETTINGS_PROJECTS); - - tabs.add(new LazyPanel() { - @Override - protected ContactPanelFull createWidget() { - final ContactPanelFull p = new ContactPanelFull(); - p.accountSettings = AccountSettings.this; - return p; - } - }, Util.C.tabContactInformation()); - tabTokens.add(PageLinks.SETTINGS_CONTACT); - - tabs.add(new LazyPanel() { - @Override - protected SshPanel createWidget() { - return new SshPanel(); - } - }, Util.C.tabSshKeys()); - tabTokens.add(PageLinks.SETTINGS_SSHKEYS); - - tabs.add(new LazyPanel() { - @Override - protected ExternalIdPanel createWidget() { - return new ExternalIdPanel(); - } - }, Util.C.tabWebIdentities()); - tabTokens.add(PageLinks.SETTINGS_WEBIDENT); - - tabs.add(new LazyPanel() { - @Override - protected MyGroupsPanel createWidget() { - return new MyGroupsPanel(); - } - }, Util.C.tabMyGroups()); - tabTokens.add(PageLinks.SETTINGS_MYGROUPS); - - if (Gerrit.getConfig().isUseContributorAgreements()) { - tabs.add(new LazyPanel() { - @Override - protected AgreementPanel createWidget() { - return new AgreementPanel(); - } - }, Util.C.tabAgreements()); - tabTokens.add(PageLinks.SETTINGS_AGREEMENTS); - } - - tabs.addSelectionHandler(new SelectionHandler() { - @Override - public void onSelection(final SelectionEvent event) { - setToken(tabTokens.get(event.getSelectedItem())); - } - }); - } - - private void infoRow(final int row, final String name) { - info.setText(row, labelIdx, name); - info.getCellFormatter().addStyleName(row, 0, - Gerrit.RESOURCES.css().header()); - } - - void display(final Account account) { - info.setText(0, fieldIdx, account.getUserName()); - info.setText(1, fieldIdx, account.getFullName()); - info.setText(2, fieldIdx, account.getPreferredEmail()); - info.setText(3, fieldIdx, mediumFormat(account.getRegisteredOn())); - info.setText(4, fieldIdx, account.getId().toString()); - } -} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java index 923a86aa63..373fa19065 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java @@ -46,8 +46,6 @@ import java.util.List; import java.util.Set; class ContactPanelShort extends Composite { - AccountSettings accountSettings; - protected final FlowPanel body; protected int labelIdx, fieldIdx; protected Button save; @@ -227,6 +225,10 @@ class ContactPanelShort extends Composite { } registerNewEmail.setEnabled(true); } + display(); + } + + void display() { } protected void row(final Grid info, final int row, final String name, @@ -354,9 +356,6 @@ class ContactPanelShort extends Composite { me.setFullName(result.getFullName()); me.setPreferredEmail(result.getPreferredEmail()); Gerrit.refreshMenuBar(); - if (accountSettings != null) { - accountSettings.display(me); - } } ContactInformation toContactInformation() { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AgreementPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java similarity index 89% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AgreementPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java index 326a1dfc80..54de4723c4 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AgreementPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyAgreementsScreen.java @@ -16,7 +16,7 @@ package com.google.gerrit.client.account; import com.google.gerrit.client.FormatUtil; 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.FancyFlexTable; import com.google.gerrit.client.ui.Hyperlink; import com.google.gerrit.common.PageLinks; @@ -26,30 +26,27 @@ import com.google.gerrit.reviewdb.AccountAgreement; import com.google.gerrit.reviewdb.AccountGroupAgreement; import com.google.gerrit.reviewdb.ContributorAgreement; import com.google.gwt.user.client.ui.Anchor; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; import com.google.gwtexpui.safehtml.client.SafeHtml; import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; -class AgreementPanel extends Composite { +public class MyAgreementsScreen extends SettingsScreen { private AgreementTable agreements; - AgreementPanel() { - final FlowPanel body = new FlowPanel(); + @Override + protected void onInitUI() { + super.onInitUI(); agreements = new AgreementTable(); - body.add(agreements); - body.add(new Hyperlink(Util.C.newAgreement(), PageLinks.SETTINGS_NEW_AGREEMENT)); - - initWidget(body); + add(agreements); + add(new Hyperlink(Util.C.newAgreement(), PageLinks.SETTINGS_NEW_AGREEMENT)); } @Override protected void onLoad() { super.onLoad(); - Util.ACCOUNT_SVC.myAgreements(new GerritCallback() { - public void onSuccess(final AgreementInfo result) { + Util.ACCOUNT_SVC.myAgreements(new ScreenLoadCallback(this) { + public void preDisplay(final AgreementInfo result) { agreements.display(result); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java new file mode 100644 index 0000000000..c542511df4 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyContactInformationScreen.java @@ -0,0 +1,31 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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; + +public class MyContactInformationScreen extends SettingsScreen { + private ContactPanelFull panel; + + @Override + protected void onInitUI() { + super.onInitUI(); + panel = new ContactPanelFull() { + @Override + void display() { + MyContactInformationScreen.this.display(); + } + }; + add(panel); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsScreen.java similarity index 67% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsScreen.java index 9ba20e82bf..b9fff040d4 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyGroupsScreen.java @@ -15,34 +15,26 @@ package com.google.gerrit.client.account; import com.google.gerrit.client.admin.GroupTable; -import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.reviewdb.AccountGroup; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import java.util.List; -class MyGroupsPanel extends Composite { +public class MyGroupsScreen extends SettingsScreen { private GroupTable groups; - MyGroupsPanel() { - final FlowPanel body = new FlowPanel(); - + @Override + protected void onInitUI() { + super.onInitUI(); groups = new GroupTable(false /* do not hyperlink to admin */); - body.add(groups); - - initWidget(body); + add(groups); } @Override protected void onLoad() { super.onLoad(); - refresh(); - } - - private void refresh() { - Util.ACCOUNT_SEC.myGroups(new GerritCallback>() { - public void onSuccess(final List result) { + Util.ACCOUNT_SEC.myGroups(new ScreenLoadCallback>(this) { + public void preDisplay(final List result) { groups.display(result); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ExternalIdPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java similarity index 94% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ExternalIdPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java index 84d8e8a2c9..5afd785181 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ExternalIdPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java @@ -18,6 +18,7 @@ import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.auth.openid.OpenIdSignInDialog; import com.google.gerrit.client.auth.openid.OpenIdUtil; import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.client.ui.FancyFlexTable; import com.google.gerrit.common.auth.SignInMode; import com.google.gerrit.common.auth.openid.OpenIdUrls; @@ -29,8 +30,6 @@ import com.google.gwt.event.logical.shared.ValueChangeHandler; import com.google.gwt.user.client.History; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; import java.util.Collections; @@ -39,16 +38,18 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -class ExternalIdPanel extends Composite { +public class MyIdentitiesScreen extends SettingsScreen { private IdTable identites; private Button deleteIdentity; - ExternalIdPanel() { - final FlowPanel body = new FlowPanel(); - body.add(new UsernamePanel()); + @Override + protected void onInitUI() { + super.onInitUI(); + + add(new UsernamePanel()); identites = new IdTable(); - body.add(identites); + add(identites); deleteIdentity = new Button(Util.C.buttonDeleteIdentity()); deleteIdentity.setEnabled(false); @@ -58,7 +59,7 @@ class ExternalIdPanel extends Composite { identites.deleteChecked(); } }); - body.add(deleteIdentity); + add(deleteIdentity); switch (Gerrit.getConfig().getAuthType()) { case OPENID: { @@ -70,21 +71,18 @@ class ExternalIdPanel extends Composite { new OpenIdSignInDialog(SignInMode.LINK_IDENTIY, to, null).center(); } }); - body.add(linkIdentity); + add(linkIdentity); break; } } - - initWidget(body); } @Override protected void onLoad() { super.onLoad(); - Util.ACCOUNT_SEC - .myExternalIds(new GerritCallback>() { - public void onSuccess(final List result) { + .myExternalIds(new ScreenLoadCallback>(this) { + public void preDisplay(final List result) { identites.display(result); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/PreferencePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java similarity index 93% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/account/PreferencePanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java index 904fb38ae7..bb81f3f85f 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/PreferencePanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPreferencesScreen.java @@ -19,6 +19,7 @@ import static com.google.gerrit.reviewdb.AccountGeneralPreferences.PAGESIZE_CHOI import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.ScreenLoadCallback; import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.AccountGeneralPreferences; import com.google.gwt.event.dom.client.ChangeEvent; @@ -28,21 +29,20 @@ import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Composite; -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.gwtjsonrpc.client.VoidResult; -class PreferencePanel extends Composite { +public class MyPreferencesScreen extends SettingsScreen { private CheckBox showSiteHeader; private CheckBox useFlashClipboard; private CheckBox copySelfOnEmails; private ListBox maximumPageSize; private Button save; - PreferencePanel() { - final FlowPanel body = new FlowPanel(); + @Override + protected void onInitUI() { + super.onInitUI(); final ClickHandler onClickSave = new ClickHandler() { @Override @@ -99,7 +99,7 @@ class PreferencePanel extends Composite { formGrid.setWidget(row, fieldIdx, maximumPageSize); row++; - body.add(formGrid); + add(formGrid); save = new Button(Util.C.buttonSaveChanges()); save.setEnabled(false); @@ -109,18 +109,15 @@ class PreferencePanel extends Composite { doSave(); } }); - body.add(save); - - initWidget(body); + add(save); } @Override protected void onLoad() { super.onLoad(); - Util.ACCOUNT_SVC.myAccount(new GerritCallback() { - public void onSuccess(final Account result) { + Util.ACCOUNT_SVC.myAccount(new ScreenLoadCallback(this) { + public void preDisplay(final Account result) { display(result.getGeneralPreferences()); - enable(true); } }); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java new file mode 100644 index 0000000000..0293b6d9c8 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java @@ -0,0 +1,78 @@ +// Copyright (C) 2008 The Android Open Source Project +// +// 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 static com.google.gerrit.client.FormatUtil.mediumFormat; + +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.reviewdb.Account; +import com.google.gwt.i18n.client.LocaleInfo; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; + +public class MyProfileScreen extends SettingsScreen { + private int labelIdx, fieldIdx; + private Grid info; + + @Override + protected void onInitUI() { + super.onInitUI(); + + if (LocaleInfo.getCurrentLocale().isRTL()) { + labelIdx = 1; + fieldIdx = 0; + } else { + labelIdx = 0; + fieldIdx = 1; + } + + info = new Grid(5, 2); + info.setStyleName(Gerrit.RESOURCES.css().infoBlock()); + info.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock()); + add(info); + + infoRow(0, Util.C.userName()); + infoRow(1, Util.C.fullName()); + infoRow(2, Util.C.preferredEmail()); + infoRow(3, Util.C.registeredOn()); + infoRow(4, Util.C.accountId()); + + final CellFormatter fmt = info.getCellFormatter(); + fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); + fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); + fmt.addStyleName(4, 0, Gerrit.RESOURCES.css().bottomheader()); + } + + @Override + protected void onLoad() { + super.onLoad(); + display(Gerrit.getUserAccount()); + display(); + } + + private void infoRow(final int row, final String name) { + info.setText(row, labelIdx, name); + info.getCellFormatter().addStyleName(row, 0, + Gerrit.RESOURCES.css().header()); + } + + void display(final Account account) { + info.setText(0, fieldIdx, account.getUserName()); + info.setText(1, fieldIdx, account.getFullName()); + info.setText(2, fieldIdx, account.getPreferredEmail()); + info.setText(3, fieldIdx, mediumFormat(account.getRegisteredOn())); + info.setText(4, fieldIdx, account.getId().toString()); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java new file mode 100644 index 0000000000..b1d6d82889 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MySshKeysScreen.java @@ -0,0 +1,31 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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; + +public class MySshKeysScreen extends SettingsScreen { + private SshPanel panel; + + @Override + protected void onInitUI() { + super.onInitUI(); + panel = new SshPanel() { + @Override + void display() { + MySshKeysScreen.this.display(); + } + }; + add(panel); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java similarity index 96% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java index 9fb3748355..eb8a8f1d47 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ProjectWatchPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.account; 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.FancyFlexTable; import com.google.gerrit.client.ui.ProjectLink; import com.google.gerrit.client.ui.ProjectNameSuggestOracle; @@ -36,7 +37,6 @@ import com.google.gwt.event.logical.shared.SelectionHandler; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.SuggestBox; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; @@ -47,7 +47,7 @@ import com.google.gwtjsonrpc.client.VoidResult; import java.util.HashSet; import java.util.List; -class ProjectWatchPanel extends Composite { +public class MyWatchedProjectsScreen extends SettingsScreen { private WatchTable watches; private Button addNew; @@ -55,8 +55,9 @@ class ProjectWatchPanel extends Composite { private Button delSel; private boolean submitOnSelection; - ProjectWatchPanel() { - final FlowPanel body = new FlowPanel(); + @Override + protected void onInitUI() { + super.onInitUI(); { final FlowPanel fp = new FlowPanel(); @@ -117,11 +118,11 @@ class ProjectWatchPanel extends Composite { } }); fp.add(addNew); - body.add(fp); + add(fp); } watches = new WatchTable(); - body.add(watches); + add(watches); { final FlowPanel fp = new FlowPanel(); delSel = new Button(Util.C.buttonDeleteSshKey()); @@ -132,10 +133,8 @@ class ProjectWatchPanel extends Composite { } }); fp.add(delSel); - body.add(fp); + add(fp); } - - initWidget(body); } void doAddNew() { @@ -166,8 +165,9 @@ class ProjectWatchPanel extends Composite { protected void onLoad() { super.onLoad(); Util.ACCOUNT_SVC - .myProjectWatch(new GerritCallback>() { - public void onSuccess(final List result) { + .myProjectWatch(new ScreenLoadCallback>( + this) { + public void preDisplay(final List result) { watches.display(result); } }); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java new file mode 100644 index 0000000000..213ccc3a71 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java @@ -0,0 +1,42 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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.Gerrit; +import com.google.gerrit.client.ui.MenuScreen; +import com.google.gerrit.common.PageLinks; + +public abstract class SettingsScreen extends MenuScreen { + public SettingsScreen() { + setRequiresSignIn(true); + + link(Util.C.tabAccountSummary(), PageLinks.SETTINGS); + link(Util.C.tabPreferences(), PageLinks.SETTINGS_PREFERENCES); + link(Util.C.tabWatchedProjects(), PageLinks.SETTINGS_PROJECTS); + link(Util.C.tabContactInformation(), PageLinks.SETTINGS_CONTACT); + link(Util.C.tabSshKeys(), PageLinks.SETTINGS_SSHKEYS); + link(Util.C.tabWebIdentities(), PageLinks.SETTINGS_WEBIDENT); + link(Util.C.tabMyGroups(), PageLinks.SETTINGS_MYGROUPS); + if (Gerrit.getConfig().isUseContributorAgreements()) { + link(Util.C.tabAgreements(), PageLinks.SETTINGS_AGREEMENTS); + } + } + + @Override + protected void onInitUI() { + super.onInitUI(); + setPageTitle(Util.C.settingsHeading()); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java index 014e514228..fba55b3c00 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SshPanel.java @@ -70,9 +70,10 @@ class SshPanel extends Composite { private Panel serverKeys; + private int loadCount; + SshPanel() { final FlowPanel body = new FlowPanel(); - body.add(new UsernamePanel()); showAddKeyBlock = new Button(Util.C.buttonShowAddSshKey()); showAddKeyBlock.addClickHandler(new ClickHandler() { @@ -320,6 +321,9 @@ class SshPanel extends Composite { if (result.isEmpty() && keys.isVisible()) { showAddKeyBlock(true); } + if (++loadCount == 2) { + display(); + } } }); @@ -329,10 +333,16 @@ class SshPanel extends Composite { for (final SshHostKey keyInfo : result) { serverKeys.add(new SshHostKeyPanel(keyInfo)); } + if (++loadCount == 2) { + display(); + } } }); } + void display() { + } + @Override protected void onUnload() { if (appletLoadTimer != null) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java index 79f67f3755..4e54e85d72 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ValidateEmailScreen.java @@ -30,7 +30,7 @@ public class ValidateEmailScreen extends AccountScreen { @Override protected void onInitUI() { super.onInitUI(); - setPageTitle(Util.C.accountSettingsHeading()); + setPageTitle(Util.C.settingsHeading()); } @Override diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java similarity index 93% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java index 75d6931f4b..14449f9cb8 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectRightsPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java @@ -17,6 +17,7 @@ package com.google.gerrit.client.admin; 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; @@ -43,7 +44,6 @@ import com.google.gwt.event.dom.client.KeyPressEvent; import com.google.gwt.event.dom.client.KeyPressHandler; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.ListBox; @@ -59,9 +59,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -public class ProjectRightsPanel extends Composite { - private Project.NameKey projectName; - +public class ProjectAccessScreen extends ProjectScreen { private Panel parentPanel; private Hyperlink parentName; @@ -74,26 +72,25 @@ public class ProjectRightsPanel extends Composite { private NpTextBox nameTxtBox; private SuggestBox nameTxt; private NpTextBox referenceTxt; + private FlowPanel addPanel; - private final FlowPanel addPanel = new FlowPanel(); + public ProjectAccessScreen(final Project.NameKey toShow) { + super(toShow); + } - public ProjectRightsPanel(final Project.NameKey toShow) { - projectName = toShow; - - final FlowPanel body = new FlowPanel(); - initParent(body); - initRights(body); - initWidget(body); + @Override + protected void onInitUI() { + super.onInitUI(); + initParent(); + initRights(); } @Override protected void onLoad() { - enableForm(false); super.onLoad(); - - Util.PROJECT_SVC.projectDetail(projectName, - new GerritCallback() { - public void onSuccess(final ProjectDetail result) { + Util.PROJECT_SVC.projectDetail(getProjectKey(), + new ScreenLoadCallback(this) { + public void preDisplay(final ProjectDetail result) { enableForm(true); display(result); } @@ -112,16 +109,17 @@ public class ProjectRightsPanel extends Composite { rangeMaxBox.setEnabled(canAdd); } - private void initParent(final Panel body) { + private void initParent() { parentPanel = new VerticalPanel(); parentPanel.add(new SmallHeading(Util.C.headingParentProjectName())); parentName = new Hyperlink("", ""); parentPanel.add(parentName); - body.add(parentPanel); + add(parentPanel); } - private void initRights(final Panel body) { + private void initRights() { + addPanel = new FlowPanel(); addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel()); final Grid addGrid = new Grid(5, 2); @@ -144,7 +142,7 @@ public class ProjectRightsPanel extends Composite { for (final ApprovalType at : Gerrit.getConfig().getApprovalTypes() .getActionTypes()) { final ApprovalCategory c = at.getCategory(); - if (Gerrit.getConfig().getWildProject().equals(projectName) + 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 @@ -228,10 +226,10 @@ public class ProjectRightsPanel extends Composite { } }); - body.add(new SmallHeading(Util.C.headingAccessRights())); - body.add(rights); - body.add(delRight); - body.add(addPanel); + add(new SmallHeading(Util.C.headingAccessRights())); + add(rights); + add(delRight); + add(addPanel); if (catBox.getItemCount() > 0) { catBox.setSelectedIndex(0); @@ -250,8 +248,7 @@ public class ProjectRightsPanel extends Composite { } parentPanel.setVisible(!isWild); - parentName.setTargetHistoryToken(Dispatcher.toProjectAdmin(parent, - ProjectAdminScreen.ACCESS_TAB)); + parentName.setTargetHistoryToken(Dispatcher.toProjectAdmin(parent, ACCESS)); parentName.setText(parent.get()); rights.display(result.groups, result.rights); @@ -262,7 +259,7 @@ public class ProjectRightsPanel extends Composite { private void doDeleteRefRights(final HashSet refRightIds) { if (!refRightIds.isEmpty()) { - Util.PROJECT_SVC.deleteRight(projectName, refRightIds, + Util.PROJECT_SVC.deleteRight(getProjectKey(), refRightIds, new GerritCallback() { @Override public void onSuccess(final ProjectDetail result) { @@ -338,8 +335,8 @@ public class ProjectRightsPanel extends Composite { } addRight.setEnabled(false); - Util.PROJECT_SVC.addRight(projectName, at.getCategory().getId(), groupName, - refPattern, min.getValue(), max.getValue(), + Util.PROJECT_SVC.addRight(getProjectKey(), at.getCategory().getId(), + groupName, refPattern, min.getValue(), max.getValue(), new GerritCallback() { public void onSuccess(final ProjectDetail result) { addRight.setEnabled(true); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java deleted file mode 100644 index 6be86572e4..0000000000 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAdminScreen.java +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (C) 2008 The Android Open Source Project -// -// 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.admin; - -import com.google.gerrit.client.Dispatcher; -import com.google.gerrit.client.Gerrit; -import com.google.gerrit.client.rpc.ScreenLoadCallback; -import com.google.gerrit.client.ui.Screen; -import com.google.gerrit.common.data.ProjectDetail; -import com.google.gerrit.reviewdb.Project; -import com.google.gwt.event.logical.shared.SelectionEvent; -import com.google.gwt.event.logical.shared.SelectionHandler; -import com.google.gwt.user.client.ui.LazyPanel; -import com.google.gwt.user.client.ui.TabPanel; - -import java.util.ArrayList; -import java.util.List; - -public class ProjectAdminScreen extends Screen { - static final String INFO_TAB = "info"; - static final String BRANCH_TAB = "branches"; - static final String ACCESS_TAB = "access"; - - private final Project.NameKey projectName; - private final String initialTabToken; - - private List tabTokens; - private TabPanel tabs; - - public ProjectAdminScreen(final Project.NameKey toShow, final String token) { - projectName = toShow; - initialTabToken = token; - } - - @Override - public boolean displayToken(String token) { - final int tabIdx = tabTokens.indexOf(token); - if (0 <= tabIdx) { - tabs.selectTab(tabIdx); - setToken(token); - return true; - } else { - return false; - } - } - - @Override - protected void onLoad() { - super.onLoad(); - Util.PROJECT_SVC.projectDetail(projectName, - new ScreenLoadCallback(this) { - @Override - protected void preDisplay(final ProjectDetail result) { - display(result); - tabs.selectTab(tabTokens.indexOf(initialTabToken)); - } - }); - } - - @Override - protected void onInitUI() { - super.onInitUI(); - tabTokens = new ArrayList(); - tabs = new TabPanel(); - tabs.setWidth("98%"); - add(tabs); - - tabs.add(new LazyPanel() { - @Override - protected ProjectInfoPanel createWidget() { - return new ProjectInfoPanel(projectName); - } - }, Util.C.projectAdminTabGeneral()); - tabTokens.add(Dispatcher.toProjectAdmin(projectName, INFO_TAB)); - - if (!Gerrit.getConfig().getWildProject().equals(projectName)) { - tabs.add(new LazyPanel() { - @Override - protected ProjectBranchesPanel createWidget() { - return new ProjectBranchesPanel(projectName); - } - }, Util.C.projectAdminTabBranches()); - tabTokens.add(Dispatcher.toProjectAdmin(projectName, BRANCH_TAB)); - } - - tabs.add(new LazyPanel() { - @Override - protected ProjectRightsPanel createWidget() { - return new ProjectRightsPanel(projectName); - } - }, Util.C.projectAdminTabAccess()); - tabTokens.add(Dispatcher.toProjectAdmin(projectName, ACCESS_TAB)); - - tabs.addSelectionHandler(new SelectionHandler() { - @Override - public void onSelection(final SelectionEvent event) { - setToken(tabTokens.get(event.getSelectedItem())); - } - }); - } - - - private void display(final ProjectDetail result) { - final Project project = result.project; - setPageTitle(Util.M.project(project.getName())); - } -} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java similarity index 93% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java index 170c49171c..8bff3e5ff5 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java @@ -18,9 +18,10 @@ import com.google.gerrit.client.ConfirmationCallback; import com.google.gerrit.client.ConfirmationDialog; 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.FancyFlexTable; -import com.google.gerrit.common.data.ListBranchesResult; import com.google.gerrit.common.data.GitwebLink; +import com.google.gerrit.common.data.ListBranchesResult; import com.google.gerrit.common.errors.InvalidNameException; import com.google.gerrit.common.errors.InvalidRevisionException; import com.google.gerrit.reviewdb.Branch; @@ -39,11 +40,9 @@ import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.ui.Anchor; import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.CheckBox; -import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HTML; -import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter; import com.google.gwtexpui.globalkey.client.NpTextBox; import com.google.gwtjsonrpc.client.RemoteJsonException; @@ -52,33 +51,24 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -public class ProjectBranchesPanel extends Composite { - private Project.NameKey projectName; - +public class ProjectBranchesScreen extends ProjectScreen { private BranchesTable branches; private Button delBranch; private Button addBranch; private NpTextBox nameTxtBox; private NpTextBox irevTxtBox; + private FlowPanel addPanel; - private final FlowPanel addPanel = new FlowPanel(); - - public ProjectBranchesPanel(final Project.NameKey toShow) { - final FlowPanel body = new FlowPanel(); - initBranches(body); - initWidget(body); - - projectName = toShow; + public ProjectBranchesScreen(final Project.NameKey toShow) { + super(toShow); } @Override protected void onLoad() { - enableForm(false); super.onLoad(); - - Util.PROJECT_SVC.listBranches(projectName, - new GerritCallback() { - public void onSuccess(final ListBranchesResult result) { + Util.PROJECT_SVC.listBranches(getProjectKey(), + new ScreenLoadCallback(this) { + public void preDisplay(final ListBranchesResult result) { enableForm(true); display(result.getBranches()); addPanel.setVisible(result.getCanAdd()); @@ -98,7 +88,11 @@ public class ProjectBranchesPanel extends Composite { irevTxtBox.setEnabled(on); } - private void initBranches(final Panel body) { + @Override + protected void onInitUI() { + super.onInitUI(); + + addPanel = new FlowPanel(); addPanel.setStyleName(Gerrit.RESOURCES.css().addSshKeyPanel()); final Grid addGrid = new Grid(2, 2); @@ -189,9 +183,9 @@ public class ProjectBranchesPanel extends Composite { } }); - body.add(branches); - body.add(delBranch); - body.add(addPanel); + add(branches); + add(delBranch); + add(addPanel); } private void doAddNewBranch() { @@ -219,7 +213,7 @@ public class ProjectBranchesPanel extends Composite { } addBranch.setEnabled(false); - Util.PROJECT_SVC.addBranch(projectName, branchName, rev, + Util.PROJECT_SVC.addBranch(getProjectKey(), branchName, rev, new GerritCallback() { public void onSuccess(final ListBranchesResult result) { addBranch.setEnabled(true); @@ -292,7 +286,7 @@ public class ProjectBranchesPanel extends Composite { new HTML(message.toString()), new ConfirmationCallback() { @Override public void onOk() { - Util.PROJECT_SVC.deleteBranch(projectName, ids, + Util.PROJECT_SVC.deleteBranch(getProjectKey(), ids, new GerritCallback>() { public void onSuccess(final Set deleted) { for (int row = 1; row < table.getRowCount();) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java similarity index 85% rename from gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java rename to gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java index 49566badd0..d308fa6c1a 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoPanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectInfoScreen.java @@ -16,6 +16,7 @@ package com.google.gerrit.client.admin; 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.SmallHeading; import com.google.gerrit.client.ui.TextSaveButtonListener; import com.google.gerrit.common.data.ProjectDetail; @@ -28,15 +29,12 @@ 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.Composite; -import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Panel; import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwtexpui.globalkey.client.NpTextArea; -public class ProjectInfoPanel extends Composite { - private Project.NameKey projectName; +public class ProjectInfoScreen extends ProjectScreen { private Project project; private Panel submitTypePanel; @@ -49,7 +47,14 @@ public class ProjectInfoPanel extends Composite { private NpTextArea descTxt; private Button saveProject; - public ProjectInfoPanel(final Project.NameKey toShow) { + public ProjectInfoScreen(final Project.NameKey toShow) { + super(toShow); + } + + @Override + protected void onInitUI() { + super.onInitUI(); + saveProject = new Button(Util.C.buttonSaveChanges()); saveProject.addClickHandler(new ClickHandler() { @Override @@ -58,28 +63,18 @@ public class ProjectInfoPanel extends Composite { } }); - final FlowPanel body = new FlowPanel(); - initDescription(body); - initSubmitType(body); - initAgreements(body); - body.add(saveProject); - - initWidget(body); - projectName = toShow; + initDescription(); + initSubmitType(); + initAgreements(); + add(saveProject); } @Override protected void onLoad() { - enableForm(false, false, false); - saveProject.setEnabled(false); super.onLoad(); - refresh(); - } - - private void refresh() { - Util.PROJECT_SVC.projectDetail(projectName, - new GerritCallback() { - public void onSuccess(final ProjectDetail result) { + Util.PROJECT_SVC.projectDetail(getProjectKey(), + new ScreenLoadCallback(this) { + public void preDisplay(final ProjectDetail result) { enableForm(result.canModifyAgreements, result.canModifyDescription, result.canModifyMergeType); saveProject.setVisible( @@ -102,7 +97,7 @@ public class ProjectInfoPanel extends Composite { canModifyAgreements || canModifyDescription || canModifyMergeType); } - private void initDescription(final Panel body) { + private void initDescription() { final VerticalPanel vp = new VerticalPanel(); vp.add(new SmallHeading(Util.C.headingDescription())); @@ -111,11 +106,11 @@ public class ProjectInfoPanel extends Composite { descTxt.setCharacterWidth(60); vp.add(descTxt); - body.add(vp); + add(vp); new TextSaveButtonListener(descTxt, saveProject); } - private void initSubmitType(final Panel body) { + private void initSubmitType() { submitTypePanel = new VerticalPanel(); submitTypePanel.add(new SmallHeading(Util.C.headingSubmitType())); @@ -130,10 +125,10 @@ public class ProjectInfoPanel extends Composite { } }); submitTypePanel.add(submitType); - body.add(submitTypePanel); + add(submitTypePanel); } - private void initAgreements(final Panel body) { + private void initAgreements() { final ValueChangeHandler onChangeSave = new ValueChangeHandler() { @Override @@ -153,7 +148,7 @@ public class ProjectInfoPanel extends Composite { useSignedOffBy.addValueChangeHandler(onChangeSave); agreementsPanel.add(useSignedOffBy); - body.add(agreementsPanel); + add(agreementsPanel); } private void setSubmitType(final Project.SubmitType newSubmitType) { @@ -203,12 +198,6 @@ public class ProjectInfoPanel extends Composite { result.canModifyDescription, result.canModifyMergeType); display(result); } - - @Override - public void onFailure(final Throwable caught) { - refresh(); - super.onFailure(caught); - } }); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java index 642712af75..e676718ee3 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectListScreen.java @@ -105,7 +105,7 @@ public class ProjectListScreen extends Screen { } private String link(final Project item) { - return Dispatcher.toProjectAdmin(item.getNameKey(), ProjectAdminScreen.INFO_TAB); + return Dispatcher.toProjectAdmin(item.getNameKey(), ProjectScreen.INFO); } void display(final List result) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java new file mode 100644 index 0000000000..2df1ba39ae --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectScreen.java @@ -0,0 +1,39 @@ +// Copyright 2010 Google Inc. All Rights Reserved. + +package com.google.gerrit.client.admin; + +import static com.google.gerrit.client.Dispatcher.toProjectAdmin; + +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.client.ui.MenuScreen; +import com.google.gerrit.reviewdb.Project; + +public abstract class ProjectScreen extends MenuScreen { + public static final String INFO = "info"; + public static final String BRANCH = "branches"; + public static final String ACCESS = "access"; + + private final Project.NameKey name; + + public ProjectScreen(final Project.NameKey toShow) { + name = toShow; + + final boolean isWild = toShow.equals(Gerrit.getConfig().getWildProject()); + + link(Util.C.projectAdminTabGeneral(), toProjectAdmin(name, INFO)); + if (!isWild) { + link(Util.C.projectAdminTabBranches(), toProjectAdmin(name, BRANCH)); + } + link(Util.C.projectAdminTabAccess(), toProjectAdmin(name, ACCESS)); + } + + protected Project.NameKey getProjectKey() { + return name; + } + + @Override + protected void onInitUI() { + super.onInitUI(); + setPageTitle(Util.M.project(name.get())); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css index a68fc15367..809e412068 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css @@ -113,6 +113,29 @@ } +/** MenuScreen **/ +.menuScreenMenuBar { + background: topMenuColor; + padding-top: 0.5em; + padding-bottom: 10em; + padding-left: 0.5em; + padding-right: 0.5em; + border-right: 1px solid black; + margin-right: 0.5em; +} + +.menuScreenMenuBar .menuItem { + white-space: nowrap; + display: block; + border-right: none; + padding: 0.2em; +} + +.menuScreenMenuBar .menuItem.activeRow { + background: selectionColor; +} + + /** CommentPanel **/ .commentPanelBorder { border-top: 1px solid lightgray; diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java index fa3deba308..035328159a 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/LinkMenuBar.java @@ -47,6 +47,18 @@ public class LinkMenuBar extends Composite { body.clear(); } + public LinkMenuItem find(String targetToken) { + for (Widget w : body) { + if (w instanceof LinkMenuItem) { + LinkMenuItem m = (LinkMenuItem) w; + if (targetToken.equals(m.getTargetHistoryToken())) { + return m; + } + } + } + return null; + } + public void add(final Widget i) { if (body.getWidgetCount() > 0) { final Widget p = body.getWidget(body.getWidgetCount() - 1); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java new file mode 100644 index 0000000000..704185cb4a --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/MenuScreen.java @@ -0,0 +1,61 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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.ui; + +import com.google.gerrit.client.Gerrit; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Widget; + +public abstract class MenuScreen extends Screen { + private final LinkMenuBar menu; + private final FlowPanel body; + + public MenuScreen() { + menu = new LinkMenuBar(); + menu.setStyleName(Gerrit.RESOURCES.css().menuScreenMenuBar()); + body = new FlowPanel(); + } + + @Override + protected void onInitUI() { + super.onInitUI(); + + HorizontalPanel hp = new HorizontalPanel(); + hp.add(menu); + hp.add(body); + super.add(hp); + } + + @Override + public void setToken(String token) { + LinkMenuItem self = menu.find(token); + if (self != null) { + self.addStyleName(Gerrit.RESOURCES.css().activeRow()); + } + super.setToken(token); + } + + @Override + protected void add(final Widget w) { + body.add(w); + } + + protected void link(String text, String target) { + final LinkMenuItem item = new LinkMenuItem(text, target); + item.setStyleName(Gerrit.RESOURCES.css().menuItem()); + menu.add(item); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java index a68ab062d7..618c7e0dc4 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/Screen.java @@ -72,7 +72,7 @@ public abstract class Screen extends View { header.insert(w, 0); } - protected final void add(final Widget w) { + protected void add(final Widget w) { body.add(w); } From c25b07b89c5009f0818f9558a4784165627e14dd Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 15 Jul 2010 01:05:13 -0700 Subject: [PATCH 7/9] Shift around username/password editing The username is now made more visible on the register screen, encouraging the user to create a new username before they set an SSH public key on their account. Username and password were removed from most tabs and put into their own HTTP Password tab, just below the SSH Public Keys. We also now have a clear password button, to permit erasing a password that was assigned and isn't actually needed by the user. The username can only be set once per account now, and once set is not permitted to be changed. This change simplifies our UI, but it also sets the stage for supporting ${user} variables in access rules for references, and renaming an account once it has branches owned by it would complicate the account rename process. Change-Id: I2c0f26bb4501b88faa451105dd3d74e3830e632c Signed-off-by: Shawn O. Pearce --- .../com/google/gerrit/common/PageLinks.java | 1 + .../gerrit/common/data/AccountSecurity.java | 4 + .../com/google/gerrit/client/Dispatcher.java | 6 + .../com/google/gerrit/client/GerritCss.java | 5 +- .../client/account/AccountConstants.java | 4 + .../account/AccountConstants.properties | 7 +- .../client/account/ContactPanelShort.java | 13 +- .../client/account/MyIdentitiesScreen.java | 2 - .../client/account/MyPasswordScreen.java | 176 +++++++++++ .../client/account/MyProfileScreen.java | 2 +- .../gerrit/client/account/RegisterScreen.java | 34 ++ .../gerrit/client/account/SettingsScreen.java | 1 + .../gerrit/client/account/UsernameField.java | 183 +++++++++++ .../gerrit/client/account/UsernamePanel.java | 297 ------------------ .../java/com/google/gerrit/client/gerrit.css | 7 +- .../com/google/gerrit/httpd/WebModule.java | 2 + .../rpc/account/AccountSecurityImpl.java | 10 + .../gerrit/server/account/ChangeUserName.java | 3 + .../gerrit/server/account/ClearPassword.java | 63 ++++ 19 files changed, 512 insertions(+), 308 deletions(-) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java delete mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernamePanel.java create mode 100644 gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java index a502b3b100..358f6566a3 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java @@ -26,6 +26,7 @@ public class PageLinks { public static final String SETTINGS = "settings"; public static final String SETTINGS_PREFERENCES = "settings,preferences"; public static final String SETTINGS_SSHKEYS = "settings,ssh-keys"; + public static final String SETTINGS_HTTP_PASSWORD = "settings,http-password"; public static final String SETTINGS_WEBIDENT = "settings,web-identities"; public static final String SETTINGS_MYGROUPS = "settings,group-memberships"; public static final String SETTINGS_AGREEMENTS = "settings,agreements"; diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java index 83d31a06ba..1117455ede 100644 --- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java +++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountSecurity.java @@ -49,6 +49,10 @@ public interface AccountSecurity extends RemoteJsonService { void generatePassword(AccountExternalId.Key key, AsyncCallback callback); + @SignInRequired + void clearPassword(AccountExternalId.Key key, + AsyncCallback gerritCallback); + @SignInRequired void myExternalIds(AsyncCallback> callback); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java index a5cd9df39b..b31399438c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java @@ -23,6 +23,7 @@ import static com.google.gerrit.common.PageLinks.REGISTER; import static com.google.gerrit.common.PageLinks.SETTINGS; import static com.google.gerrit.common.PageLinks.SETTINGS_AGREEMENTS; import static com.google.gerrit.common.PageLinks.SETTINGS_CONTACT; +import static com.google.gerrit.common.PageLinks.SETTINGS_HTTP_PASSWORD; import static com.google.gerrit.common.PageLinks.SETTINGS_MYGROUPS; import static com.google.gerrit.common.PageLinks.SETTINGS_NEW_AGREEMENT; import static com.google.gerrit.common.PageLinks.SETTINGS_PREFERENCES; @@ -35,6 +36,7 @@ import com.google.gerrit.client.account.MyAgreementsScreen; import com.google.gerrit.client.account.MyContactInformationScreen; import com.google.gerrit.client.account.MyGroupsScreen; import com.google.gerrit.client.account.MyIdentitiesScreen; +import com.google.gerrit.client.account.MyPasswordScreen; import com.google.gerrit.client.account.MyPreferencesScreen; import com.google.gerrit.client.account.MyProfileScreen; import com.google.gerrit.client.account.MySshKeysScreen; @@ -331,6 +333,10 @@ public class Dispatcher { return new MyIdentitiesScreen(); } + if (token.equals(SETTINGS_HTTP_PASSWORD)) { + return new MyPasswordScreen(); + } + if (token.equals(SETTINGS_MYGROUPS)) { return new MyGroupsScreen(); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java index 8cea4b693e..40fe73117e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java @@ -25,6 +25,8 @@ public interface GerritCss extends CssResource { String accountDashboard(); String accountInfoBlock(); String accountName(); + String accountUsername(); + String accountPassword(); String activeRow(); String addReviewer(); String removeReviewer(); @@ -169,8 +171,6 @@ public interface GerritCss extends CssResource { String sshHostKeyPanelKnownHostEntry(); String sshKeyPanelEncodedKey(); String sshKeyPanelInvalid(); - String sshPanelUsername(); - String sshPanelPassword(); String topmenu(); String topmenuMenuLeft(); String topmenuMenuRight(); @@ -178,5 +178,6 @@ public interface GerritCss extends CssResource { String topmenuTDmenu(); String topmost(); String useridentity(); + String usernameField(); String version(); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java index fd5e030c91..e161c14237 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.java @@ -36,6 +36,7 @@ public interface AccountConstants extends Constants { String tabWatchedProjects(); String tabContactInformation(); String tabSshKeys(); + String tabHttpAccess(); String tabWebIdentities(); String tabMyGroups(); String tabAgreements(); @@ -49,7 +50,9 @@ public interface AccountConstants extends Constants { String userName(); String password(); + String buttonSetUserName(); String buttonChangeUserName(); + String buttonClearPassword(); String buttonGeneratePassword(); String invalidUserName(); @@ -117,6 +120,7 @@ public interface AccountConstants extends Constants { String welcomeToGerritCodeReview(); String welcomeReviewContact(); String welcomeContactFrom(); + String welcomeUsernameHeading(); String welcomeSshKeyHeading(); String welcomeSshKeyText(); String welcomeAgreementHeading(); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties index b8cdd076f6..b74add47d7 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/AccountConstants.properties @@ -17,6 +17,7 @@ tabPreferences = Preferences tabWatchedProjects = Watched Projects tabContactInformation = Contact Information tabSshKeys = SSH Public Keys +tabHttpAccess = HTTP Password tabWebIdentities = Identities tabMyGroups = Groups tabAgreements = Agreements @@ -30,8 +31,10 @@ buttonAddSshKey = Add userName = Username password = Password +buttonSetUserName = Select Username buttonChangeUserName = Change Username -buttonGeneratePassword = Regenerate +buttonClearPassword = Clear Password +buttonGeneratePassword = Generate Password invalidUserName = Username must contain only letters, numbers, _, - or . sshKeyInvalid = Invalid Key @@ -113,6 +116,8 @@ welcomeContactFrom = \ you are to others, and to send updates to code reviews you have either \ started or subscribed to.

+welcomeUsernameHeading = Select a unique username: + welcomeSshKeyHeading = Register an SSH public key: welcomeSshKeyText = \

Gerrit Code Review uses \ diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java index 373fa19065..21c9163f69 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/ContactPanelShort.java @@ -20,6 +20,7 @@ import com.google.gerrit.client.ui.TextSaveButtonListener; import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.AccountExternalId; import com.google.gerrit.reviewdb.ContactInformation; +import com.google.gerrit.reviewdb.Account.FieldName; import com.google.gwt.event.dom.client.ChangeEvent; import com.google.gwt.event.dom.client.ChangeHandler; import com.google.gwt.event.dom.client.ClickEvent; @@ -98,12 +99,18 @@ class ContactPanelShort extends Composite { emailLine.add(registerNewEmail); } - row(infoPlainText, 0, Util.C.contactFieldFullName(), nameTxt); - row(infoPlainText, 1, Util.C.contactFieldEmail(), emailLine); + int row = 0; + if (!Gerrit.getConfig().canEdit(FieldName.USER_NAME)) { + infoPlainText.resizeRows(infoPlainText.getRowCount() + 1); + row(infoPlainText, row++, Util.C.userName(), new UsernameField()); + } + + row(infoPlainText, row++, Util.C.contactFieldFullName(), nameTxt); + row(infoPlainText, row++, Util.C.contactFieldEmail(), emailLine); infoPlainText.getCellFormatter().addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); infoPlainText.getCellFormatter().addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); - infoPlainText.getCellFormatter().addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader()); + infoPlainText.getCellFormatter().addStyleName(row - 1, 0, Gerrit.RESOURCES.css().bottomheader()); save = new Button(Util.C.buttonSaveChanges()); save.setEnabled(false); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java index 5afd785181..f3816f2fc4 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyIdentitiesScreen.java @@ -46,8 +46,6 @@ public class MyIdentitiesScreen extends SettingsScreen { protected void onInitUI() { super.onInitUI(); - add(new UsernamePanel()); - identites = new IdTable(); add(identites); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java new file mode 100644 index 0000000000..2202ac88c0 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyPasswordScreen.java @@ -0,0 +1,176 @@ +// Copyright (C) 2008 The Android Open Source Project +// +// 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 static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME; + +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.rpc.ScreenLoadCallback; +import com.google.gerrit.reviewdb.AccountExternalId; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.i18n.client.LocaleInfo; +import com.google.gwt.user.client.ui.Button; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.Widget; +import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; +import com.google.gwtexpui.clippy.client.CopyableLabel; + +import java.util.List; + +public class MyPasswordScreen extends SettingsScreen { + private CopyableLabel password; + private Button generatePassword; + private Button clearPassword; + private AccountExternalId id; + + @Override + protected void onInitUI() { + super.onInitUI(); + + password = new CopyableLabel(""); + password.addStyleName(Gerrit.RESOURCES.css().accountPassword()); + + generatePassword = new Button(Util.C.buttonGeneratePassword()); + generatePassword.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + doGeneratePassword(); + } + }); + + clearPassword = new Button(Util.C.buttonClearPassword()); + clearPassword.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + doClearPassword(); + } + }); + + final Grid userInfo = new Grid(2, 2); + final CellFormatter fmt = userInfo.getCellFormatter(); + userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock()); + userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock()); + add(userInfo); + + row(userInfo, 0, Util.C.userName(), new UsernameField()); + row(userInfo, 1, Util.C.password(), password); + + fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); + fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); + fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader()); + + final FlowPanel buttons = new FlowPanel(); + buttons.add(generatePassword); + buttons.add(clearPassword); + add(buttons); + } + + @Override + protected void onLoad() { + super.onLoad(); + + enableUI(false); + Util.ACCOUNT_SEC + .myExternalIds(new ScreenLoadCallback>(this) { + public void preDisplay(final List result) { + AccountExternalId id = null; + for (AccountExternalId i : result) { + if (i.isScheme(SCHEME_USERNAME)) { + id = i; + break; + } + } + display(id); + } + }); + } + + private void display(AccountExternalId id) { + String user, pass; + if (id != null) { + user = id.getSchemeRest(); + pass = id.getPassword(); + } else { + user = null; + pass = null; + } + this.id = id; + + Gerrit.getUserAccount().setUserName(user); + + password.setText(pass != null ? pass : ""); + password.setVisible(pass != null); + + enableUI(true); + } + + private void row(final Grid info, final int row, final String name, + final Widget field) { + final CellFormatter fmt = info.getCellFormatter(); + if (LocaleInfo.getCurrentLocale().isRTL()) { + info.setText(row, 1, name); + info.setWidget(row, 0, field); + fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().header()); + } else { + info.setText(row, 0, name); + info.setWidget(row, 1, field); + fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header()); + } + } + + private void doGeneratePassword() { + if (id != null) { + enableUI(false); + Util.ACCOUNT_SEC.generatePassword(id.getKey(), + new GerritCallback() { + public void onSuccess(final AccountExternalId result) { + display(result); + } + + @Override + public void onFailure(final Throwable caught) { + enableUI(true); + } + }); + } + } + + private void doClearPassword() { + if (id != null) { + enableUI(false); + Util.ACCOUNT_SEC.clearPassword(id.getKey(), + new GerritCallback() { + public void onSuccess(final AccountExternalId result) { + display(result); + } + + @Override + public void onFailure(final Throwable caught) { + enableUI(true); + } + }); + } + } + + private void enableUI(boolean on) { + on &= id != null; + + generatePassword.setEnabled(on); + clearPassword.setVisible(on && id.getPassword() != null); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java index 0293b6d9c8..65c2590b0e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyProfileScreen.java @@ -69,7 +69,7 @@ public class MyProfileScreen extends SettingsScreen { } void display(final Account account) { - info.setText(0, fieldIdx, account.getUserName()); + info.setWidget(0, fieldIdx, new UsernameField()); info.setText(1, fieldIdx, account.getFullName()); info.setText(2, fieldIdx, account.getPreferredEmail()); info.setText(3, fieldIdx, mediumFormat(account.getRegisteredOn())); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java index f43d1ac2a2..8c99d45389 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/RegisterScreen.java @@ -20,9 +20,13 @@ import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.client.ui.SmallHeading; import com.google.gerrit.common.PageLinks; import com.google.gerrit.reviewdb.Account; +import com.google.gerrit.reviewdb.Account.FieldName; +import com.google.gwt.i18n.client.LocaleInfo; import com.google.gwt.user.client.ui.FlowPanel; import com.google.gwt.user.client.ui.FormPanel; +import com.google.gwt.user.client.ui.Grid; import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; public class RegisterScreen extends AccountScreen { private final String nextToken; @@ -65,6 +69,36 @@ public class RegisterScreen extends AccountScreen { }); formBody.add(contactGroup); + if (Gerrit.getUserAccount().getUserName() == null + && Gerrit.getConfig().canEdit(FieldName.USER_NAME)) { + final FlowPanel fp = new FlowPanel(); + fp.setStyleName(Gerrit.RESOURCES.css().registerScreenSection()); + fp.add(new SmallHeading(Util.C.welcomeUsernameHeading())); + + final Grid userInfo = new Grid(1, 2); + final CellFormatter fmt = userInfo.getCellFormatter(); + userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock()); + userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock()); + fp.add(userInfo); + + fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); + fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); + fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().bottomheader()); + + UsernameField field = new UsernameField(); + if (LocaleInfo.getCurrentLocale().isRTL()) { + userInfo.setText(0, 1, Util.C.userName()); + userInfo.setWidget(0, 0, field); + fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().header()); + } else { + userInfo.setText(0, 0, Util.C.userName()); + userInfo.setWidget(0, 1, field); + fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().header()); + } + + formBody.add(fp); + } + final FlowPanel sshKeyGroup = new FlowPanel(); sshKeyGroup.setStyleName(Gerrit.RESOURCES.css().registerScreenSection()); sshKeyGroup.add(new SmallHeading(Util.C.welcomeSshKeyHeading())); diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java index 213ccc3a71..93560182ef 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/SettingsScreen.java @@ -27,6 +27,7 @@ public abstract class SettingsScreen extends MenuScreen { link(Util.C.tabWatchedProjects(), PageLinks.SETTINGS_PROJECTS); link(Util.C.tabContactInformation(), PageLinks.SETTINGS_CONTACT); link(Util.C.tabSshKeys(), PageLinks.SETTINGS_SSHKEYS); + link(Util.C.tabHttpAccess(), PageLinks.SETTINGS_HTTP_PASSWORD); link(Util.C.tabWebIdentities(), PageLinks.SETTINGS_WEBIDENT); link(Util.C.tabMyGroups(), PageLinks.SETTINGS_MYGROUPS); if (Gerrit.getConfig().isUseContributorAgreements()) { diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java new file mode 100644 index 0000000000..93ccb7431a --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java @@ -0,0 +1,183 @@ +// Copyright (C) 2008 The Android Open Source Project +// +// 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.ErrorDialog; +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.client.rpc.GerritCallback; +import com.google.gerrit.client.ui.TextSaveButtonListener; +import com.google.gerrit.common.errors.InvalidUserNameException; +import com.google.gerrit.reviewdb.Account; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +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.user.client.ui.Button; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.FlowPanel; +import com.google.gwt.user.client.ui.TextBox; +import com.google.gwtexpui.clippy.client.CopyableLabel; +import com.google.gwtexpui.globalkey.client.NpTextBox; +import com.google.gwtjsonrpc.client.VoidResult; + +class UsernameField extends Composite { + private CopyableLabel userNameLbl; + private NpTextBox userNameTxt; + private Button setUserName; + + UsernameField() { + String user = Gerrit.getUserAccount().getUserName(); + userNameLbl = new CopyableLabel(user != null ? user : ""); + userNameLbl.setStyleName(Gerrit.RESOURCES.css().accountUsername()); + + if (user != null || !canEditUserName()) { + initWidget(userNameLbl); + + } else { + final FlowPanel body = new FlowPanel(); + initWidget(body); + setStyleName(Gerrit.RESOURCES.css().usernameField()); + + userNameTxt = new NpTextBox(); + userNameTxt.addKeyPressHandler(new UserNameValidator()); + userNameTxt.addStyleName(Gerrit.RESOURCES.css().accountUsername()); + userNameTxt.setVisibleLength(16); + userNameTxt.addKeyPressHandler(new KeyPressHandler() { + @Override + public void onKeyPress(KeyPressEvent event) { + if (event.getCharCode() == KeyCodes.KEY_ENTER) { + doSetUserName(); + } + } + }); + + setUserName = new Button(Util.C.buttonSetUserName()); + setUserName.setVisible(canEditUserName()); + setUserName.setEnabled(false); + setUserName.addClickHandler(new ClickHandler() { + @Override + public void onClick(final ClickEvent event) { + doSetUserName(); + } + }); + new TextSaveButtonListener(userNameTxt, setUserName); + + userNameLbl.setVisible(false); + body.add(userNameLbl); + body.add(userNameTxt); + body.add(setUserName); + } + } + + private boolean canEditUserName() { + return Gerrit.getConfig().canEdit(Account.FieldName.USER_NAME); + } + + private void doSetUserName() { + if (!canEditUserName()) { + return; + } + + String newName = userNameTxt.getText(); + if ("".equals(newName)) { + newName = null; + } + if (newName != null && !newName.matches(Account.USER_NAME_PATTERN)) { + invalidUserName(); + return; + } + + enableUI(false); + + final String newUserName = newName; + Util.ACCOUNT_SEC.changeUserName(newUserName, + new GerritCallback() { + public void onSuccess(final VoidResult result) { + Gerrit.getUserAccount().setUserName(newUserName); + userNameLbl.setText(newUserName); + userNameLbl.setVisible(true); + userNameTxt.setVisible(false); + setUserName.setVisible(false); + } + + @Override + public void onFailure(final Throwable caught) { + enableUI(true); + if (InvalidUserNameException.MESSAGE.equals(caught.getMessage())) { + invalidUserName(); + } else { + super.onFailure(caught); + } + } + }); + } + + private void invalidUserName() { + new ErrorDialog(Util.C.invalidUserName()).center(); + } + + private void enableUI(final boolean on) { + userNameTxt.setEnabled(on); + setUserName.setEnabled(on); + } + + private final class UserNameValidator implements KeyPressHandler { + @Override + public void onKeyPress(final KeyPressEvent event) { + final char code = event.getCharCode(); + switch (code) { + case KeyCodes.KEY_ALT: + case KeyCodes.KEY_BACKSPACE: + case KeyCodes.KEY_CTRL: + case KeyCodes.KEY_DELETE: + case KeyCodes.KEY_DOWN: + case KeyCodes.KEY_END: + case KeyCodes.KEY_ENTER: + case KeyCodes.KEY_ESCAPE: + case KeyCodes.KEY_HOME: + case KeyCodes.KEY_LEFT: + case KeyCodes.KEY_PAGEDOWN: + case KeyCodes.KEY_PAGEUP: + case KeyCodes.KEY_RIGHT: + case KeyCodes.KEY_SHIFT: + case KeyCodes.KEY_TAB: + case KeyCodes.KEY_UP: + // Allow these, even if one of their assigned codes is + // identical to an ASCII character we do not want to + // allow in the box. + // + // We still want to let the user move around the input box + // with their arrow keys, or to move between fields using tab. + // Invalid characters introduced will be caught through the + // server's own validation of the input data. + // + break; + + default: + final TextBox box = (TextBox) event.getSource(); + final String re; + if (box.getCursorPos() == 0) + re = Account.USER_NAME_PATTERN_FIRST; + else + re = Account.USER_NAME_PATTERN_REST; + if (!String.valueOf(code).matches("^" + re + "$")) { + event.preventDefault(); + event.stopPropagation(); + } + } + } + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernamePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernamePanel.java deleted file mode 100644 index 2ec20d0f5c..0000000000 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernamePanel.java +++ /dev/null @@ -1,297 +0,0 @@ -// Copyright (C) 2008 The Android Open Source Project -// -// 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 static com.google.gerrit.reviewdb.AccountExternalId.SCHEME_USERNAME; - -import com.google.gerrit.client.ErrorDialog; -import com.google.gerrit.client.Gerrit; -import com.google.gerrit.client.rpc.GerritCallback; -import com.google.gerrit.client.ui.TextSaveButtonListener; -import com.google.gerrit.common.errors.InvalidUserNameException; -import com.google.gerrit.reviewdb.Account; -import com.google.gerrit.reviewdb.AccountExternalId; -import com.google.gwt.event.dom.client.ClickEvent; -import com.google.gwt.event.dom.client.ClickHandler; -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.i18n.client.LocaleInfo; -import com.google.gwt.user.client.ui.Button; -import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.TextBox; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; -import com.google.gwtexpui.clippy.client.CopyableLabel; -import com.google.gwtexpui.globalkey.client.NpTextBox; -import com.google.gwtjsonrpc.client.VoidResult; - -import java.util.List; - -public class UsernamePanel extends Composite { - private NpTextBox userNameTxt; - private Button changeUserName; - - private CopyableLabel password; - private Button generatePassword; - - private AccountExternalId.Key idKey; - - UsernamePanel() { - final FlowPanel body = new FlowPanel(); - initWidget(body); - - userNameTxt = new NpTextBox(); - userNameTxt.addKeyPressHandler(new UserNameValidator()); - userNameTxt.addStyleName(Gerrit.RESOURCES.css().sshPanelUsername()); - userNameTxt.setVisibleLength(16); - userNameTxt.setReadOnly(!canEditUserName()); - userNameTxt.addKeyPressHandler(new KeyPressHandler() { - @Override - public void onKeyPress(KeyPressEvent event) { - if (event.getCharCode() == KeyCodes.KEY_ENTER) { - doChangeUserName(); - } - } - }); - - changeUserName = new Button(Util.C.buttonChangeUserName()); - changeUserName.setVisible(canEditUserName()); - changeUserName.setEnabled(false); - changeUserName.addClickHandler(new ClickHandler() { - @Override - public void onClick(final ClickEvent event) { - doChangeUserName(); - } - }); - new TextSaveButtonListener(userNameTxt, changeUserName); - - password = new CopyableLabel(""); - password.addStyleName(Gerrit.RESOURCES.css().sshPanelPassword()); - password.setVisible(false); - - generatePassword = new Button(Util.C.buttonGeneratePassword()); - generatePassword.addClickHandler(new ClickHandler() { - @Override - public void onClick(ClickEvent event) { - doGeneratePassword(); - } - }); - - final Grid userInfo = new Grid(2, 3); - final CellFormatter fmt = userInfo.getCellFormatter(); - userInfo.setStyleName(Gerrit.RESOURCES.css().infoBlock()); - userInfo.addStyleName(Gerrit.RESOURCES.css().accountInfoBlock()); - body.add(userInfo); - - row(userInfo, 0, Util.C.userName(), userNameTxt, changeUserName); - row(userInfo, 1, Util.C.password(), password, generatePassword); - - fmt.addStyleName(0, 0, Gerrit.RESOURCES.css().topmost()); - fmt.addStyleName(0, 1, Gerrit.RESOURCES.css().topmost()); - fmt.addStyleName(0, 2, Gerrit.RESOURCES.css().topmost()); - - fmt.addStyleName(1, 0, Gerrit.RESOURCES.css().bottomheader()); - } - - @Override - protected void onLoad() { - super.onLoad(); - - enableUI(false); - Util.ACCOUNT_SEC - .myExternalIds(new GerritCallback>() { - public void onSuccess(final List result) { - AccountExternalId id = null; - for (AccountExternalId i : result) { - if (i.isScheme(SCHEME_USERNAME)) { - id = i; - break; - } - } - display(id); - } - }); - } - - private void display(AccountExternalId id) { - String user, pass; - if (id != null) { - idKey = id.getKey(); - user = id.getSchemeRest(); - pass = id.getPassword(); - } else { - idKey = null; - user = null; - pass = null; - } - - Gerrit.getUserAccount().setUserName(user); - userNameTxt.setText(user); - userNameTxt.setEnabled(true); - generatePassword.setEnabled(idKey != null); - - if (pass != null) { - password.setText(pass); - password.setVisible(true); - } else { - password.setVisible(false); - } - } - - private void row(final Grid info, final int row, final String name, - final Widget field1, final Widget field2) { - final CellFormatter fmt = info.getCellFormatter(); - if (LocaleInfo.getCurrentLocale().isRTL()) { - info.setText(row, 2, name); - info.setWidget(row, 1, field1); - info.setWidget(row, 0, field2); - fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder()); - fmt.addStyleName(row, 2, Gerrit.RESOURCES.css().header()); - } else { - info.setText(row, 0, name); - info.setWidget(row, 1, field1); - info.setWidget(row, 2, field2); - fmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder()); - fmt.addStyleName(row, 0, Gerrit.RESOURCES.css().header()); - } - } - - private boolean canEditUserName() { - return Gerrit.getConfig().canEdit(Account.FieldName.USER_NAME); - } - - void doChangeUserName() { - if (!canEditUserName()) { - return; - } - - String newName = userNameTxt.getText(); - if ("".equals(newName)) { - newName = null; - } - if (newName != null && !newName.matches(Account.USER_NAME_PATTERN)) { - invalidUserName(); - return; - } - - enableUI(false); - - final String newUserName = newName; - Util.ACCOUNT_SEC.changeUserName(newUserName, - new GerritCallback() { - public void onSuccess(final VoidResult result) { - Gerrit.getUserAccount().setUserName(newUserName); - enableUI(true); - } - - @Override - public void onFailure(final Throwable caught) { - enableUI(true); - if (InvalidUserNameException.MESSAGE.equals(caught.getMessage())) { - invalidUserName(); - } else { - super.onFailure(caught); - } - } - }); - } - - void invalidUserName() { - userNameTxt.setFocus(true); - new ErrorDialog(Util.C.invalidUserName()).center(); - } - - void doGeneratePassword() { - if (idKey == null) { - return; - } - - enableUI(false); - - Util.ACCOUNT_SEC.generatePassword(idKey, - new GerritCallback() { - public void onSuccess(final AccountExternalId result) { - enableUI(true); - display(result); - } - - @Override - public void onFailure(final Throwable caught) { - enableUI(true); - if (InvalidUserNameException.MESSAGE.equals(caught.getMessage())) { - invalidUserName(); - } else { - super.onFailure(caught); - } - } - }); - } - - private void enableUI(final boolean on) { - userNameTxt.setEnabled(on); - changeUserName.setEnabled(on); - generatePassword.setEnabled(on && idKey != null); - } - - private final class UserNameValidator implements KeyPressHandler { - @Override - public void onKeyPress(final KeyPressEvent event) { - final char code = event.getCharCode(); - switch (code) { - case KeyCodes.KEY_ALT: - case KeyCodes.KEY_BACKSPACE: - case KeyCodes.KEY_CTRL: - case KeyCodes.KEY_DELETE: - case KeyCodes.KEY_DOWN: - case KeyCodes.KEY_END: - case KeyCodes.KEY_ENTER: - case KeyCodes.KEY_ESCAPE: - case KeyCodes.KEY_HOME: - case KeyCodes.KEY_LEFT: - case KeyCodes.KEY_PAGEDOWN: - case KeyCodes.KEY_PAGEUP: - case KeyCodes.KEY_RIGHT: - case KeyCodes.KEY_SHIFT: - case KeyCodes.KEY_TAB: - case KeyCodes.KEY_UP: - // Allow these, even if one of their assigned codes is - // identical to an ASCII character we do not want to - // allow in the box. - // - // We still want to let the user move around the input box - // with their arrow keys, or to move between fields using tab. - // Invalid characters introduced will be caught through the - // server's own validation of the input data. - // - break; - - default: - final TextBox box = (TextBox) event.getSource(); - final String re; - if (box.getCursorPos() == 0) - re = Account.USER_NAME_PATTERN_FIRST; - else - re = Account.USER_NAME_PATTERN_REST; - if (!String.valueOf(code).matches("^" + re + "$")) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } -} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css index 809e412068..2b2fbcccc2 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css @@ -984,11 +984,14 @@ a:hover.downloadLink { /** AccountSettings **/ -.sshPanelUsername { +.usernameField { + white-space: nowrap; +} +.accountUsername { font-family: mono-font; font-size: small; } -.sshPanelPassword { +.accountPassword { font-family: mono-font; font-size: small; } diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java index 17a7ba5eeb..93b6d09a0d 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/WebModule.java @@ -29,6 +29,7 @@ import com.google.gerrit.server.IdentifiedUser; import com.google.gerrit.server.RemotePeer; import com.google.gerrit.server.account.AccountManager; import com.google.gerrit.server.account.ChangeUserName; +import com.google.gerrit.server.account.ClearPassword; import com.google.gerrit.server.account.GeneratePassword; import com.google.gerrit.server.config.AuthConfig; import com.google.gerrit.server.config.CanonicalWebUrl; @@ -139,6 +140,7 @@ public class WebModule extends FactoryModule { bind(AccountManager.class); bind(ChangeUserName.CurrentUser.class); factory(ChangeUserName.Factory.class); + factory(ClearPassword.Factory.class); factory(GeneratePassword.Factory.class); bind(SocketAddress.class).annotatedWith(RemotePeer.class).toProvider( diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java index 11c2d9dda7..77662a18a3 100644 --- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java +++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountSecurityImpl.java @@ -37,6 +37,7 @@ import com.google.gerrit.server.account.AccountException; import com.google.gerrit.server.account.AccountManager; import com.google.gerrit.server.account.AuthRequest; import com.google.gerrit.server.account.ChangeUserName; +import com.google.gerrit.server.account.ClearPassword; import com.google.gerrit.server.account.GeneratePassword; import com.google.gerrit.server.account.Realm; import com.google.gerrit.server.config.AuthConfig; @@ -75,6 +76,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements private final AccountManager accountManager; private final boolean useContactInfo; + private final ClearPassword.Factory clearPasswordFactory; private final GeneratePassword.Factory generatePasswordFactory; private final ChangeUserName.CurrentUser changeUserNameFactory; private final DeleteExternalIds.Factory deleteExternalIdsFactory; @@ -88,6 +90,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements final RegisterNewEmailSender.Factory esf, final SshKeyCache skc, final AccountByEmailCache abec, final AccountCache uac, final AccountManager am, + final ClearPassword.Factory clearPasswordFactory, final GeneratePassword.Factory generatePasswordFactory, final ChangeUserName.CurrentUser changeUserNameFactory, final DeleteExternalIds.Factory deleteExternalIdsFactory, @@ -106,6 +109,7 @@ class AccountSecurityImpl extends BaseServiceImplementation implements useContactInfo = contactStore != null && contactStore.isEnabled(); + this.clearPasswordFactory = clearPasswordFactory; this.generatePasswordFactory = generatePasswordFactory; this.changeUserNameFactory = changeUserNameFactory; this.deleteExternalIdsFactory = deleteExternalIdsFactory; @@ -183,6 +187,12 @@ class AccountSecurityImpl extends BaseServiceImplementation implements Handler.wrap(generatePasswordFactory.create(key)).to(callback); } + @Override + public void clearPassword(AccountExternalId.Key key, + AsyncCallback callback) { + Handler.wrap(clearPasswordFactory.create(key)).to(callback); + } + public void myExternalIds(AsyncCallback> callback) { externalIdDetailFactory.create().to(callback); } diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java index 1509299447..e875a19933 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java @@ -91,6 +91,9 @@ public class ChangeUserName implements Callable { public VoidResult call() throws OrmException, NameAlreadyUsedException, InvalidUserNameException { final Collection old = old(); + if (!old.isEmpty()) { + throw new IllegalStateException("Username cannot be changed."); + } if (newUsername != null && !newUsername.isEmpty()) { if (!USER_NAME_PATTERN.matcher(newUsername).matches()) { diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java new file mode 100644 index 0000000000..1fc87fe411 --- /dev/null +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ClearPassword.java @@ -0,0 +1,63 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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.server.account; + +import com.google.gerrit.common.errors.NoSuchEntityException; +import com.google.gerrit.reviewdb.AccountExternalId; +import com.google.gerrit.reviewdb.ReviewDb; +import com.google.gerrit.server.IdentifiedUser; +import com.google.gwtorm.client.OrmException; +import com.google.inject.Inject; +import com.google.inject.assistedinject.Assisted; + +import java.util.Collections; +import java.util.concurrent.Callable; + +/** Operation to clear a password for an account. */ +public class ClearPassword implements Callable { + public interface Factory { + ClearPassword create(AccountExternalId.Key forUser); + } + + private final AccountCache accountCache; + private final ReviewDb db; + private final IdentifiedUser user; + + private final AccountExternalId.Key forUser; + + @Inject + ClearPassword(final AccountCache accountCache, final ReviewDb db, + final IdentifiedUser user, + + @Assisted AccountExternalId.Key forUser) { + this.accountCache = accountCache; + this.db = db; + this.user = user; + + this.forUser = forUser; + } + + public AccountExternalId call() throws OrmException, NoSuchEntityException { + AccountExternalId id = db.accountExternalIds().get(forUser); + if (id == null || !user.getAccountId().equals(id.getAccountId())) { + throw new NoSuchEntityException(); + } + + id.setPassword(null); + db.accountExternalIds().update(Collections.singleton(id)); + accountCache.evict(user.getAccountId()); + return id; + } +} From 9b218bc0ad9e1ac2fbbb46e3f4bd12691e0cd323 Mon Sep 17 00:00:00 2001 From: Sasa Zivkov Date: Mon, 5 Jul 2010 10:00:15 +0200 Subject: [PATCH 8/9] Show commit message on the per-file review pages. When reviewing changes the review may be interrupted for any number of reasons. When continuing the review process the review might have forgotten the content of the commit message. This change shows the commit message at the per-file review page. The area for the commit message is limited in order to preserve the space for the diff view(s). If the commit message doesn't fit into the commit message area a vertical/horizontal scrollbar will appear. The commit message for the patch set to the right side (the "new version") of the PatchScreen is cached to avoid one RPC every time the patch screen switches to next/prev file. Bug: issue 426 Bug: issue 680 Change-Id: I8db497e44cadab6be8895e1c477516d3b3b2d9c2 Signed-off-by: Sasa Zivkov Signed-off-by: Shawn O. Pearce --- .../com/google/gerrit/client/Dispatcher.java | 8 +- .../changes/ChangeDescriptionBlock.java | 21 +-- .../client/changes/CommitMessageBlock.java | 54 +++++++ .../PatchSetComplexDisclosurePanel.java | 6 +- .../gerrit/client/changes/PatchTable.java | 51 ++++--- .../client/changes/PublishCommentScreen.java | 5 +- .../gerrit/client/patches/NavLinks.java | 105 ++++++++++++++ .../gerrit/client/patches/PatchScreen.java | 133 +++++++++--------- .../google/gerrit/client/ui/PatchLink.java | 22 ++- 9 files changed, 287 insertions(+), 118 deletions(-) create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java create mode 100644 gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java index b31399438c..099939543e 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Dispatcher.java @@ -70,6 +70,7 @@ import com.google.gerrit.client.changes.PublishCommentScreen; import com.google.gerrit.client.patches.PatchScreen; import com.google.gerrit.client.ui.Screen; import com.google.gerrit.common.auth.SignInMode; +import com.google.gerrit.common.data.PatchSetDetail; import com.google.gerrit.reviewdb.Account; import com.google.gerrit.reviewdb.AccountGroup; import com.google.gerrit.reviewdb.Change; @@ -124,7 +125,7 @@ public class Dispatcher { private static void select(final String token) { if (token.startsWith("patch,")) { - patch(token, null, 0, null); + patch(token, null, 0, null, null); } else if (token.startsWith("change,publish,")) { publish(token); @@ -268,7 +269,8 @@ public class Dispatcher { } public static void patch(String token, final Patch.Key id, - final int patchIndex, final PatchTable patchTable) { + final int patchIndex, final PatchSetDetail patchSetDetail, + final PatchTable patchTable) { GWT.runAsync(new AsyncSplit(token) { public void onSuccess() { Gerrit.display(token, select()); @@ -282,6 +284,7 @@ public class Dispatcher { return new PatchScreen.SideBySide( // id != null ? id : Patch.Key.parse(skip(p, token)), // patchIndex, // + patchSetDetail, // patchTable // ); } @@ -291,6 +294,7 @@ public class Dispatcher { return new PatchScreen.Unified( // id != null ? id : Patch.Key.parse(skip(p, token)), // patchIndex, // + patchSetDetail, // patchTable // ); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java index 4ca965e94b..05323263fd 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeDescriptionBlock.java @@ -14,42 +14,29 @@ package com.google.gerrit.client.changes; -import com.google.gerrit.client.Gerrit; -import com.google.gerrit.client.ui.CommentLinkProcessor; import com.google.gerrit.common.data.AccountInfoCache; import com.google.gerrit.reviewdb.Change; import com.google.gerrit.reviewdb.PatchSetInfo; import com.google.gwt.user.client.ui.Composite; -import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HorizontalPanel; -import com.google.gwtexpui.safehtml.client.SafeHtml; -import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; public class ChangeDescriptionBlock extends Composite { private final ChangeInfoBlock infoBlock; - private final HTML description; + private final CommitMessageBlock messageBlock; public ChangeDescriptionBlock() { infoBlock = new ChangeInfoBlock(); - description = new HTML(); - description.setStyleName(Gerrit.RESOURCES.css().changeScreenDescription()); + messageBlock = new CommitMessageBlock(); final HorizontalPanel hp = new HorizontalPanel(); hp.add(infoBlock); - hp.add(description); + hp.add(messageBlock); initWidget(hp); } public void display(final Change chg, final PatchSetInfo info, final AccountInfoCache acc) { infoBlock.display(chg, acc); - - SafeHtml msg = new SafeHtmlBuilder().append(info.getMessage()); - msg = msg.linkify(); - msg = CommentLinkProcessor.apply(msg); - msg = new SafeHtmlBuilder().openElement("p").append(msg).closeElement("p"); - msg = msg.replaceAll("\n\n", "

"); - msg = msg.replaceAll("\n", "
"); - SafeHtml.set(description, msg); + messageBlock.display(info.getMessage()); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java new file mode 100644 index 0000000000..48e257de34 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommitMessageBlock.java @@ -0,0 +1,54 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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.Gerrit; +import com.google.gerrit.client.ui.CommentLinkProcessor; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwtexpui.safehtml.client.SafeHtml; +import com.google.gwtexpui.safehtml.client.SafeHtmlBuilder; + +public class CommitMessageBlock extends Composite { + private final HTML description; + + public CommitMessageBlock() { + this(null); + } + + public CommitMessageBlock(String height) { + description = new HTML(); + description.setStyleName(Gerrit.RESOURCES.css().changeScreenDescription()); + if (height != null) { + ScrollPanel scrollPanel = new ScrollPanel(); + scrollPanel.setHeight(height); + scrollPanel.add(description); + initWidget(scrollPanel); + } else { + initWidget(description); + } + } + + public void display(final String commitMessage) { + SafeHtml msg = new SafeHtmlBuilder().append(commitMessage); + msg = msg.linkify(); + msg = CommentLinkProcessor.apply(msg); + msg = new SafeHtmlBuilder().openElement("p").append(msg).closeElement("p"); + msg = msg.replaceAll("\n\n", "

"); + msg = msg.replaceAll("\n", "
"); + SafeHtml.set(description, msg); + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java index 2a4ea1888f..394723e209 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java @@ -147,7 +147,7 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements O patchTable = new PatchTable(); patchTable.setSavePointerId("PatchTable " + patchSet.getId()); - patchTable.display(info.getKey(), detail.getPatches()); + patchTable.display(detail); body.add(infoTable); @@ -419,7 +419,7 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements O @Override public void onClick(ClickEvent event) { for (Patch p : detail.getPatches()) { - SideBySide link = new PatchLink.SideBySide(p.getFileName(), p.getKey(), 0, null); + SideBySide link = new PatchLink.SideBySide(p.getFileName(), p.getKey(), 0, null, null); Window.open(link.getElement().toString(), p.getFileName(), null); } } @@ -432,7 +432,7 @@ class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements O @Override public void onClick(ClickEvent event) { for (Patch p : detail.getPatches()) { - Unified link = new PatchLink.Unified(p.getFileName(), p.getKey(), 0, null); + Unified link = new PatchLink.Unified(p.getFileName(), p.getKey(), 0, null, null); Window.open(link.getElement().toString(), p.getFileName(), null); } } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java index bfe9effb7b..2611890b1c 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java @@ -19,8 +19,8 @@ import com.google.gerrit.client.patches.PatchScreen; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.client.ui.NavigationTable; import com.google.gerrit.client.ui.PatchLink; +import com.google.gerrit.common.data.PatchSetDetail; import com.google.gerrit.reviewdb.Patch; -import com.google.gerrit.reviewdb.PatchSet; import com.google.gerrit.reviewdb.Patch.Key; import com.google.gwt.core.client.GWT; import com.google.gwt.event.dom.client.ClickEvent; @@ -46,7 +46,7 @@ import java.util.List; public class PatchTable extends Composite { private final FlowPanel myBody; - private PatchSet.Id psid; + private PatchSetDetail detail; private Command onLoadCommand; private MyTable myTable; private String savePointerId; @@ -57,12 +57,21 @@ public class PatchTable extends Composite { initWidget(myBody); } - public void display(final PatchSet.Id id, final List list) { - psid = id; - myTable = null; - patchList = list; + public int indexOf(Patch.Key patch) { + for (int i = 0; i < patchList.size(); i++) { + if (patchList.get(i).getKey().equals(patch)) { + return i; + } + } + return -1; + } - final DisplayCommand cmd = new DisplayCommand(list); + public void display(PatchSetDetail detail) { + this.detail = detail; + this.patchList = detail.getPatches(); + myTable = null; + + final DisplayCommand cmd = new DisplayCommand(patchList); if (cmd.execute()) { cmd.initMeter(); DeferredCommand.addCommand(cmd); @@ -144,9 +153,9 @@ public class PatchTable extends Composite { PatchLink link; if (patchType == PatchScreen.Type.SIDE_BY_SIDE && patch.getPatchType() == Patch.PatchType.UNIFIED) { - link = new PatchLink.SideBySide("", thisKey, index, this); + link = new PatchLink.SideBySide("", thisKey, index, detail, this); } else { - link = new PatchLink.Unified("", thisKey, index, this); + link = new PatchLink.Unified("", thisKey, index, detail, this); } SafeHtmlBuilder text = new SafeHtmlBuilder(); text.append(before); @@ -274,11 +283,13 @@ public class PatchTable extends Composite { Widget nameCol; if (patch.getPatchType() == Patch.PatchType.UNIFIED) { - nameCol = new PatchLink.SideBySide(patch.getFileName(), patch.getKey(), row - 1, - PatchTable.this); + nameCol = + new PatchLink.SideBySide(patch.getFileName(), patch.getKey(), + row - 1, detail, PatchTable.this); } else { - nameCol = new PatchLink.Unified(patch.getFileName(), patch.getKey(), row - 1, - PatchTable.this); + nameCol = + new PatchLink.Unified(patch.getFileName(), patch.getKey(), row - 1, + detail, PatchTable.this); } if (patch.getSourceFileName() != null) { final String text; @@ -300,16 +311,16 @@ public class PatchTable extends Composite { int C_UNIFIED = C_SIDEBYSIDE + 1; if (patch.getPatchType() == Patch.PatchType.UNIFIED) { - table.setWidget(row, C_SIDEBYSIDE, - new PatchLink.SideBySide(Util.C.patchTableDiffSideBySide(), patch.getKey(), row - 1, - PatchTable.this)); + table.setWidget(row, C_SIDEBYSIDE, new PatchLink.SideBySide(Util.C + .patchTableDiffSideBySide(), patch.getKey(), row - 1, detail, + PatchTable.this)); } else if (patch.getPatchType() == Patch.PatchType.BINARY) { C_UNIFIED = C_SIDEBYSIDE + 2; } - table.setWidget(row, C_UNIFIED, - new PatchLink.Unified(Util.C.patchTableDiffUnified(), patch.getKey(), row - 1, - PatchTable.this)); + table.setWidget(row, C_UNIFIED, new PatchLink.Unified(Util.C + .patchTableDiffUnified(), patch.getKey(), row - 1, detail, + PatchTable.this)); } void appendHeader(final SafeHtmlBuilder m) { @@ -599,7 +610,7 @@ public class PatchTable extends Composite { void initMeter() { if (meter == null) { - meter = new ProgressBar(Util.M.loadingPatchSet(psid.get())); + meter = new ProgressBar(Util.M.loadingPatchSet(detail.getPatchSet().getId().get())); PatchTable.this.myBody.clear(); PatchTable.this.myBody.add(meter); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java index d0d148eb03..0335178391 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java @@ -281,10 +281,7 @@ public class PublishCommentScreen extends AccountScreen implements draftsPanel.add(panel); // Parent table can be null here since we are not showing any // next/previous links - panel.add(new PatchLink.SideBySide(fn, patchKey, 0, null /* - * parent - * table - */)); + panel.add(new PatchLink.SideBySide(fn, patchKey, 0, null, null)); priorFile = fn; } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java new file mode 100644 index 0000000000..6aae855f55 --- /dev/null +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/NavLinks.java @@ -0,0 +1,105 @@ +// Copyright (C) 2010 The Android Open Source Project +// +// 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.patches; + +import com.google.gerrit.client.Gerrit; +import com.google.gerrit.client.changes.PatchTable; +import com.google.gerrit.client.changes.Util; +import com.google.gerrit.client.ui.ChangeLink; +import com.google.gerrit.client.ui.InlineHyperlink; +import com.google.gerrit.reviewdb.Change; +import com.google.gwt.event.dom.client.KeyPressEvent; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Grid; +import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; +import com.google.gwtexpui.globalkey.client.KeyCommand; +import com.google.gwtexpui.globalkey.client.KeyCommandSet; +import com.google.gwtexpui.safehtml.client.SafeHtml; + +class NavLinks extends Composite { + private final KeyCommandSet keys; + private final Grid table; + + private InlineHyperlink prev; + private InlineHyperlink next; + + private KeyCommand prevKey; + private KeyCommand nextKey; + + NavLinks(KeyCommandSet kcs, Change.Id forChange) { + keys = kcs; + table = new Grid(1, 3); + initWidget(table); + + final CellFormatter fmt = table.getCellFormatter(); + table.setStyleName(Gerrit.RESOURCES.css().sideBySideScreenLinkTable()); + fmt.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT); + fmt.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER); + fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT); + + final ChangeLink up = new ChangeLink("", forChange); + SafeHtml.set(up, SafeHtml.asis(Util.C.upToChangeIconLink())); + table.setWidget(0, 1, up); + } + + void display(int patchIndex, PatchScreen.Type type, PatchTable fileList) { + if (fileList != null) { + prev = fileList.getPreviousPatchLink(patchIndex, type); + next = fileList.getNextPatchLink(patchIndex, type); + } else { + prev = null; + next = null; + } + + if (prev != null) { + if (keys != null && prevKey == null) { + prevKey = new KeyCommand(0, '[', PatchUtil.C.previousFileHelp()) { + @Override + public void onKeyPress(KeyPressEvent event) { + prev.go(); + } + }; + keys.add(prevKey); + } + table.setWidget(0, 0, prev); + } else { + if (keys != null && prevKey != null) { + keys.remove(prevKey); + prevKey = null; + } + table.clearCell(0, 0); + } + + if (next != null) { + if (keys != null && nextKey == null) { + nextKey = new KeyCommand(0, ']', PatchUtil.C.nextFileHelp()) { + @Override + public void onKeyPress(KeyPressEvent event) { + next.go(); + } + }; + keys.add(nextKey); + } + table.setWidget(0, 2, next); + } else { + if (keys != null && nextKey != null) { + keys.remove(nextKey); + nextKey = null; + } + table.clearCell(0, 2); + } + } +} diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java index d576097ac2..9ecd161291 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java @@ -18,11 +18,11 @@ import com.google.gerrit.client.Dispatcher; import com.google.gerrit.client.Gerrit; import com.google.gerrit.client.RpcStatus; import com.google.gerrit.client.changes.ChangeScreen; +import com.google.gerrit.client.changes.CommitMessageBlock; import com.google.gerrit.client.changes.PatchTable; import com.google.gerrit.client.changes.Util; import com.google.gerrit.client.rpc.GerritCallback; import com.google.gerrit.client.rpc.ScreenLoadCallback; -import com.google.gerrit.client.ui.ChangeLink; import com.google.gerrit.client.ui.InlineHyperlink; import com.google.gerrit.client.ui.Screen; import com.google.gerrit.common.PageLinks; @@ -48,15 +48,12 @@ import com.google.gwt.user.client.DeferredCommand; import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.DisclosurePanel; import com.google.gwt.user.client.ui.FlowPanel; -import com.google.gwt.user.client.ui.Grid; -import com.google.gwt.user.client.ui.HasHorizontalAlignment; +import com.google.gwt.user.client.ui.HorizontalPanel; import com.google.gwt.user.client.ui.Label; -import com.google.gwt.user.client.ui.Widget; -import com.google.gwt.user.client.ui.HTMLTable.CellFormatter; +import com.google.gwt.user.client.ui.VerticalPanel; import com.google.gwtexpui.globalkey.client.GlobalKey; import com.google.gwtexpui.globalkey.client.KeyCommand; import com.google.gwtexpui.globalkey.client.KeyCommandSet; -import com.google.gwtexpui.safehtml.client.SafeHtml; import com.google.gwtjsonrpc.client.VoidResult; public abstract class PatchScreen extends Screen implements @@ -65,8 +62,8 @@ public abstract class PatchScreen extends Screen implements public static class SideBySide extends PatchScreen { public SideBySide(final Patch.Key id, final int patchIndex, - final PatchTable patchTable) { - super(id, patchIndex, patchTable); + final PatchSetDetail patchSetDetail, final PatchTable patchTable) { + super(id, patchIndex, patchSetDetail, patchTable); } @Override @@ -82,8 +79,8 @@ public abstract class PatchScreen extends Screen implements public static class Unified extends PatchScreen { public Unified(final Patch.Key id, final int patchIndex, - final PatchTable patchTable) { - super(id, patchIndex, patchTable); + final PatchSetDetail patchSetDetail, final PatchTable patchTable) { + super(id, patchIndex, patchSetDetail, patchTable); final PatchScriptSettings s = settingsPanel.getValue(); s.getPrettySettings().setSyntaxHighlighting(false); settingsPanel.setValue(s); @@ -103,6 +100,7 @@ public abstract class PatchScreen extends Screen implements // Which patch set id's are being diff'ed private static PatchSet.Id diffSideA = null; private static PatchSet.Id diffSideB = null; + private static Boolean historyOpen = null; private static final OpenHandler cacheOpenState = new OpenHandler() { @@ -123,6 +121,7 @@ public abstract class PatchScreen extends Screen implements private static Change.Id currentChangeId = null; protected final Patch.Key patchKey; + protected PatchSetDetail patchSetDetail; protected PatchTable fileList; protected PatchSet.Id idSideA; protected PatchSet.Id idSideB; @@ -133,6 +132,9 @@ public abstract class PatchScreen extends Screen implements private FlowPanel contentPanel; private Label noDifference; private AbstractPatchContentTable contentTable; + private CommitMessageBlock commitMessageBlock; + private NavLinks topNav; + private NavLinks bottomNav; private int rpcSequence; private PatchScript lastScript; @@ -150,9 +152,6 @@ public abstract class PatchScreen extends Screen implements /** Link to the screen for the next file, null if not applicable */ private InlineHyperlink nextFileLink; - private static final char SHORTCUT_PREVIOUS_FILE = '['; - private static final char SHORTCUT_NEXT_FILE = ']'; - /** * How this patch should be displayed in the patch screen. */ @@ -161,8 +160,9 @@ public abstract class PatchScreen extends Screen implements } protected PatchScreen(final Patch.Key id, final int patchIndex, - final PatchTable patchTable) { + final PatchSetDetail detail, final PatchTable patchTable) { patchKey = id; + patchSetDetail = detail; fileList = patchTable; // If we have any diff side stored, make sure they are applicable to the @@ -270,8 +270,17 @@ public abstract class PatchScreen extends Screen implements || (historyOpen != null && historyOpen)); historyPanel.addOpenHandler(cacheOpenState); historyPanel.addCloseHandler(cacheCloseState); - add(historyPanel); - add(settingsPanel); + + + VerticalPanel vp = new VerticalPanel(); + vp.add(historyPanel); + vp.add(settingsPanel); + commitMessageBlock = new CommitMessageBlock("6em"); + HorizontalPanel hp = new HorizontalPanel(); + hp.setWidth("100%"); + hp.add(vp); + hp.add(commitMessageBlock); + add(hp); noDifference = new Label(PatchUtil.C.noDifference()); noDifference.setStyleName(Gerrit.RESOURCES.css().patchNoDifference()); @@ -280,35 +289,23 @@ public abstract class PatchScreen extends Screen implements contentTable = createContentTable(); contentTable.fileList = fileList; - add(createNextPrevLinks()); + topNav = + new NavLinks(keysNavigation, patchKey.getParentKey().getParentKey()); + bottomNav = new NavLinks(null, patchKey.getParentKey().getParentKey()); + + add(topNav); contentPanel = new FlowPanel(); contentPanel.setStyleName(Gerrit.RESOURCES.css() .sideBySideScreenSideBySideTable()); contentPanel.add(noDifference); contentPanel.add(contentTable); add(contentPanel); - add(createNextPrevLinks()); + add(bottomNav); - // This must be done after calling createNextPrevLinks(), which initializes - // these fields - if (previousFileLink != null) { - installLinkShortCut(previousFileLink, SHORTCUT_PREVIOUS_FILE, PatchUtil.C - .previousFileHelp()); + if (fileList != null) { + topNav.display(patchIndex, getPatchScreenType(), fileList); + bottomNav.display(patchIndex, getPatchScreenType(), fileList); } - if (nextFileLink != null) { - installLinkShortCut(nextFileLink, SHORTCUT_NEXT_FILE, PatchUtil.C - .nextFileHelp()); - } - } - - private void installLinkShortCut(final InlineHyperlink link, char shortcut, - String help) { - keysNavigation.add(new KeyCommand(0, shortcut, help) { - @Override - public void onKeyPress(KeyPressEvent event) { - link.go(); - } - }); } void setReviewedByCurrentUser(boolean reviewed) { @@ -330,36 +327,28 @@ public abstract class PatchScreen extends Screen implements }); } - private Widget createNextPrevLinks() { - final Grid table = new Grid(1, 3); - final CellFormatter fmt = table.getCellFormatter(); - table.setStyleName(Gerrit.RESOURCES.css().sideBySideScreenLinkTable()); - fmt.setHorizontalAlignment(0, 0, HasHorizontalAlignment.ALIGN_LEFT); - fmt.setHorizontalAlignment(0, 1, HasHorizontalAlignment.ALIGN_CENTER); - fmt.setHorizontalAlignment(0, 2, HasHorizontalAlignment.ALIGN_RIGHT); - - if (fileList != null) { - previousFileLink = - fileList.getPreviousPatchLink(patchIndex, getPatchScreenType()); - table.setWidget(0, 0, previousFileLink); - - nextFileLink = - fileList.getNextPatchLink(patchIndex, getPatchScreenType()); - table.setWidget(0, 2, nextFileLink); - } - - final ChangeLink up = - new ChangeLink("", patchKey.getParentKey().getParentKey()); - SafeHtml.set(up, SafeHtml.asis(Util.C.upToChangeIconLink())); - table.setWidget(0, 1, up); - - return table; - } - @Override protected void onLoad() { super.onLoad(); - refresh(true); + if (patchSetDetail == null) { + Util.DETAIL_SVC.patchSetDetail(idSideB, + new GerritCallback() { + @Override + public void onSuccess(PatchSetDetail result) { + patchSetDetail = result; + if (fileList == null) { + fileList = new PatchTable(); + fileList.display(result); + patchIndex = fileList.indexOf(patchKey); + topNav.display(patchIndex, getPatchScreenType(), fileList); + bottomNav.display(patchIndex, getPatchScreenType(), fileList); + } + refresh(true); + } + }); + } else { + refresh(true); + } } @Override @@ -417,6 +406,20 @@ public abstract class PatchScreen extends Screen implements setWindowTitle(PatchUtil.M.patchWindowTitle(cid.abbreviate(), fileName)); setPageTitle(PatchUtil.M.patchPageTitle(cid.abbreviate(), path)); + if (idSideB.equals(patchSetDetail.getPatchSet().getId())) { + commitMessageBlock.setVisible(true); + commitMessageBlock.display(patchSetDetail.getInfo().getMessage()); + } else { + commitMessageBlock.setVisible(false); + Util.DETAIL_SVC.patchSetDetail(idSideB, + new GerritCallback() { + @Override + public void onSuccess(PatchSetDetail result) { + commitMessageBlock.display(result.getInfo().getMessage()); + } + }); + } + historyTable.display(script.getHistory()); historyPanel.setVisible(true); @@ -500,7 +503,7 @@ public abstract class PatchScreen extends Screen implements Util.DETAIL_SVC.patchSetDetail(psid, new GerritCallback() { public void onSuccess(final PatchSetDetail result) { - fileList.display(psid, result.getPatches()); + fileList.display(result); } }); } diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java index 6a34826235..9979edf659 100644 --- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java +++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/PatchLink.java @@ -16,11 +16,13 @@ package com.google.gerrit.client.ui; import com.google.gerrit.client.Dispatcher; import com.google.gerrit.client.changes.PatchTable; +import com.google.gerrit.common.data.PatchSetDetail; import com.google.gerrit.reviewdb.Patch; public abstract class PatchLink extends InlineHyperlink { protected Patch.Key patchKey; protected int patchIndex; + protected PatchSetDetail patchSetDetail; protected PatchTable parentPatchTable; /** @@ -28,14 +30,17 @@ public abstract class PatchLink extends InlineHyperlink { * @param patchKey The key for this patch * @param patchIndex The index of the current patch in the patch set * @param historyToken The history token + * @parma patchSetDetail Detailed information about the patch set. * @param parentPatchTable The table used to display this link */ public PatchLink(final String text, final Patch.Key patchKey, final int patchIndex, final String historyToken, - PatchTable parentPatchTable) { + final PatchSetDetail patchSetDetail, + final PatchTable parentPatchTable) { super(text, historyToken); this.patchKey = patchKey; this.patchIndex = patchIndex; + this.patchSetDetail = patchSetDetail; this.parentPatchTable = parentPatchTable; } @@ -45,23 +50,26 @@ public abstract class PatchLink extends InlineHyperlink { getTargetHistoryToken(), // patchKey, // patchIndex, // + patchSetDetail, // parentPatchTable // ); } public static class SideBySide extends PatchLink { public SideBySide(final String text, final Patch.Key patchKey, - final int patchIndex, PatchTable parentPatchTable) { - super(text, patchKey, patchIndex, Dispatcher - .toPatchSideBySide(patchKey), parentPatchTable); + final int patchIndex, PatchSetDetail patchSetDetail, + PatchTable parentPatchTable) { + super(text, patchKey, patchIndex, Dispatcher.toPatchSideBySide(patchKey), + patchSetDetail, parentPatchTable); } } public static class Unified extends PatchLink { public Unified(final String text, final Patch.Key patchKey, - final int patchIndex, PatchTable parentPatchTable) { - super(text, patchKey, patchIndex, - Dispatcher.toPatchUnified(patchKey), parentPatchTable); + final int patchIndex, PatchSetDetail patchSetDetail, + PatchTable parentPatchTable) { + super(text, patchKey, patchIndex, Dispatcher.toPatchUnified(patchKey), + patchSetDetail, parentPatchTable); } } } From 1a602a8274a8f84ebd5ef2cfe1893e7d4c1f817b Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Thu, 15 Jul 2010 09:44:26 -0700 Subject: [PATCH 9/9] Fix missing semicolon in index_postgres Change-Id: Id7294ef83b8c19c862953b06fc8df5a6e00a22cc Signed-off-by: Shawn O. Pearce --- .../resources/com/google/gerrit/reviewdb/index_postgres.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql index 2f1e65b7f3..b44351cd77 100644 --- a/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql +++ b/gerrit-reviewdb/src/main/resources/com/google/gerrit/reviewdb/index_postgres.sql @@ -88,7 +88,7 @@ ON account_group_members (group_id); -- @PrimaryKey covers: byAccount -- covers: byProject CREATE INDEX account_project_watches_byProject -ON account_project_watches (project_name) +ON account_project_watches (project_name); -- *********************************************************************