James Moger
2014-06-04 c9921bd3b0b7bf90b6e5e2a52141c3fdf0f31f89
Revise the user profile page and add a preferences form
8 files modified
223 ■■■■ changed files
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties 9 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/UserPage.html 51 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/pages/UserPage.java 153 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/panels/BooleanOption.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/panels/ChoiceOption.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/panels/TextOption.html 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
@@ -722,4 +722,11 @@
gb.gc = GC 
gb.garbageCollection = Garbage Collection
gb.garbageCollectionDescription = The garbage collector will pack loose objects pushed from clients and will remove unreferenced objects from the repository.
gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup.
gb.commitMessageRendererDescription = Commit messages can be displayed as plaintext or as rendered markup.
gb.preferences = preferences
gb.accountPreferences = Account Preferences
gb.accountPreferencesDescription = Specify your account preferences
gb.languagePreference = Language Preference
gb.languagePreferenceDescription = Select your preferred translation for the Gitblit UI
gb.displayNameDescription = The preferred name for display
gb.emailAddressDescription = The primary email address for receiving notifications
src/main/java/com/gitblit/wicket/pages/UserPage.html
@@ -7,27 +7,19 @@
<body>
<wicket:extend>
<div class="container">
    <div class="row" style="padding-top:10px;">
        <div class="span4">
            <div wicket:id="gravatar"></div>
            <div style="text-align: left;">
                <h2><span wicket:id="userDisplayName"></span></h2>
                <div><i class="icon-user"></i> <span wicket:id="userUsername"></span></div>
                <div><i class="icon-envelope"></i><span wicket:id="userEmail"></span></div>
            </div>
    <div class="row" style="padding-top:15px;">
        <div class="span3">
            <div wicket:id="userTitlePanel"></div>
        </div>
        <div class="span8">
            <div class="pull-right">
                <a class="btn-small" wicket:id="newRepository" style="padding-right:0px;">
                    <i class="icon icon-plus-sign"></i>
                    <wicket:message key="gb.newRepository"></wicket:message>
                </a>
            </div>
            <div class="tabbable">
    </div>
    <div class="row" style="padding-top:10px;">
        <div class="span12">
            <div class="tabbable tabs-left">
                <!-- tab titles -->
                <ul class="nav nav-tabs">
                    <li class="active"><a href="#repositories" data-toggle="tab"><wicket:message key="gb.repositories"></wicket:message></a></li>
                    <div wicket:id="preferencesLink"></div>
                </ul>
    
                <!-- tab content -->
@@ -41,11 +33,36 @@
                            </tbody>
                        </table>
                    </div>
                    <!-- preferences tab -->
                    <div wicket:id="preferencesTab"></div>
                </div>
            </div>
        </div>
    </div>
</div>
<wicket:fragment wicket:id="preferencesLinkFragment">
    <li><a href="#preferences" data-toggle="tab"><wicket:message key="gb.preferences"></wicket:message></a></li>
</wicket:fragment>
<wicket:fragment wicket:id="preferencesTabFragment">
    <div class="tab-pane" id="preferences">
        <h4><wicket:message key="gb.accountPreferences"></wicket:message></h4>
        <p><wicket:message key="gb.accountPreferencesDescription"></wicket:message></p>
        <hr />
        <form wicket:id="prefsForm">
            <div wicket:id="displayName"></div>
            <div wicket:id="emailAddress"></div>
            <div wicket:id="language"></div>
            <div class="form-actions"><input class="btn btn-appmenu" type="submit" value="Save" wicket:message="value:gb.save" wicket:id="save" /></div>
        </form>
    </div>
</wicket:fragment>
</wicket:extend>
</body>
</html>
src/main/java/com/gitblit/wicket/pages/UserPage.java
@@ -15,19 +15,27 @@
 */
package com.gitblit.wicket.pages;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import org.apache.wicket.PageParameters;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.link.BookmarkablePageLink;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.panel.Fragment;
import org.apache.wicket.markup.repeater.Item;
import org.apache.wicket.markup.repeater.data.DataView;
import org.apache.wicket.markup.repeater.data.ListDataProvider;
import org.eclipse.jgit.lib.PersonIdent;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;
import com.gitblit.GitBlitException;
import com.gitblit.Keys;
import com.gitblit.models.Menu.ParameterMenuItem;
import com.gitblit.models.NavLink;
@@ -40,9 +48,10 @@
import com.gitblit.wicket.GitBlitWebSession;
import com.gitblit.wicket.GitblitRedirectException;
import com.gitblit.wicket.WicketUtils;
import com.gitblit.wicket.panels.GravatarImage;
import com.gitblit.wicket.panels.LinkPanel;
import com.gitblit.wicket.panels.ChoiceOption;
import com.gitblit.wicket.panels.ProjectRepositoryPanel;
import com.gitblit.wicket.panels.TextOption;
import com.gitblit.wicket.panels.UserTitlePanel;
public class UserPage extends RootPage {
@@ -83,21 +92,18 @@
            user = new UserModel(userName);
        }
        add(new Label("userDisplayName", user.getDisplayName()));
        add(new Label("userUsername", user.username));
        LinkPanel email = new LinkPanel("userEmail", null, user.emailAddress, "mailto:#");
        email.setRenderBodyOnly(true);
        add(email.setVisible(app().settings().getBoolean(Keys.web.showEmailAddresses, true) && !StringUtils.isEmpty(user.emailAddress)));
        PersonIdent person = new PersonIdent(user.getDisplayName(), user.emailAddress == null ? user.getDisplayName() : user.emailAddress);
        add(new GravatarImage("gravatar", person, 210));
        add(new UserTitlePanel("userTitlePanel", user, user.username));
        UserModel sessionUser = GitBlitWebSession.get().getUser();
        if (sessionUser != null && user.canCreate() && sessionUser.equals(user)) {
            // user can create personal repositories
            add(new BookmarkablePageLink<Void>("newRepository", app().getNewRepositoryPage()));
        boolean isMyProfile = sessionUser != null && sessionUser.equals(user);
        if (isMyProfile) {
            addPreferences(user);
        } else {
            add(new Label("newRepository").setVisible(false));
            // visiting user
            add(new Label("preferencesLink").setVisible(false));
            add(new Label("preferencesTab").setVisible(false));
        }
        List<RepositoryModel> repositories = getRepositories(params);
@@ -145,4 +151,121 @@
        navLinks.add(menu);
    }
    private void addPreferences(UserModel user) {
        // add preferences
        Form<Void> prefs = new Form<Void>("prefsForm");
        List<Language> languages = Arrays.asList(
                new Language("English","en"),
                new Language("Español", "es"),
                new Language("Français", "fr"),
                new Language("日本語", "ja"),
                new Language("한국말", "ko"),
                new Language("Nederlands", "nl"),
                new Language("Norsk", "no"),
                new Language("Język Polski", "pl"),
                new Language("Português", "pt_BR"),
                new Language("中文", "zh_CN"));
        String lc = user.getPreferences().locale;
        if (StringUtils.isEmpty(lc)) {
            // user has not specified language preference
            // try server default preference
            lc = app().settings().getString(Keys.web.forceDefaultLocale, null);
            if (StringUtils.isEmpty(lc)) {
                // server default language is not configured
                // try browser preference
                Locale sessionLocale = GitBlitWebSession.get().getLocale();
                if (sessionLocale != null) {
                    lc = sessionLocale.getLanguage() + "_" + sessionLocale.getCountry();
                }
            }
        }
        Language preferredLanguage = null;
        if (!StringUtils.isEmpty(lc)) {
            for (Language language : languages) {
                if (language.code.equals(lc)) {
                    // language_COUNTRY match
                    preferredLanguage = language;
                } else if (preferredLanguage != null && lc.startsWith(language.code)) {
                    // language match, but not COUNTRY match
                    preferredLanguage = language;
                }
            }
        }
        final IModel<String> displayName = Model.of(user.getDisplayName());
        final IModel<String> emailAddress = Model.of(user.emailAddress == null ? "" : user.emailAddress);
        final IModel<Language> language = Model.of(preferredLanguage);
        prefs.add(new TextOption("displayName",
                getString("gb.displayName"),
                getString("gb.displayNameDescription"),
                displayName).setVisible(app().authentication().supportsDisplayNameChanges(user)));
        prefs.add(new TextOption("emailAddress",
                getString("gb.emailAddress"),
                getString("gb.emailAddressDescription"),
                emailAddress).setVisible(app().authentication().supportsEmailAddressChanges(user)));
        prefs.add(new ChoiceOption<Language>("language",
                getString("gb.languagePreference"),
                getString("gb.languagePreferenceDescription"),
                language,
                languages));
        prefs.add(new AjaxButton("save") {
            private static final long serialVersionUID = 1L;
            @Override
            protected void onSubmit(AjaxRequestTarget target, Form<?> form) {
                UserModel user = GitBlitWebSession.get().getUser();
                user.displayName = displayName.getObject();
                user.emailAddress = emailAddress.getObject();
                Language lang = language.getObject();
                if (lang != null) {
                    user.getPreferences().locale = lang.code;
                }
                try {
                    app().gitblit().reviseUser(user.username, user);
                    setRedirect(true);
                    setResponsePage(UserPage.class, WicketUtils.newUsernameParameter(user.username));
                } catch (GitBlitException e) {
                    // logger.error("Failed to update user " + user.username, e);
                    // error(getString("gb.failedToUpdateUser"), false);
                }
            }
        });
        // add the preferences tab
        add(new Fragment("preferencesLink", "preferencesLinkFragment", this).setRenderBodyOnly(true));
        Fragment fragment = new Fragment("preferencesTab", "preferencesTabFragment", this);
        fragment.add(prefs);
        add(fragment.setRenderBodyOnly(true));
    }
    private class Language implements Serializable {
        private static final long serialVersionUID = 1L;
        final String name;
        final String code;
        public Language(String name, String code) {
            this.name = name;
            this.code = code;
        }
        @Override
        public String toString() {
            return name + " (" + code +")";
        }
    }
}
src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html
@@ -13,7 +13,7 @@
    <div wicket:id="policiesGroup">
        <div wicket:id="policies" style="padding-top:4px;">
            <div>
                <label style="font-weight:bold;"><input type="radio" wicket:id="radio" /> <img wicket:id="image"></img> <span wicket:id="name"></span></label>
                <label style="font-weight:bold;margin-bottom:1px;"><input type="radio" wicket:id="radio" /> <img wicket:id="image"></img> <span wicket:id="name"></span></label>
            </div>
            <label class="checkbox" style="color:#777;" wicket:id="description"></label>
        </div>
src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html
@@ -8,7 +8,7 @@
<wicket:panel>
    <div style="padding-top:4px;">
        <div>
            <label style="font-weight:bold;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label>
            <label style="font-weight:bold;margin-bottom:1px;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label>
        </div>
        <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>
        <p style="padding-top:5px;"><select class="span3" wicket:id="choice" /></p>
src/main/java/com/gitblit/wicket/panels/BooleanOption.html
@@ -8,7 +8,7 @@
<wicket:panel>
    <div style="padding-top:4px;">
        <div>
            <label style="font-weight:bold;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label>
            <label style="font-weight:bold;margin-bottom:1px;" class="checkbox"><input type="checkbox" wicket:id="checkbox" /> <span wicket:id="name"></span></label>
        </div>
        <label class="checkbox" style="color:#777;" wicket:id="description"></label>
    </div>
src/main/java/com/gitblit/wicket/panels/ChoiceOption.html
@@ -7,7 +7,7 @@
<body>
<wicket:panel>
    <div style="padding-top:4px;">
        <div>
        <div style="margin-bottom:1px;">
            <b><span wicket:id="name"></span></b>
        </div>
        <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>
src/main/java/com/gitblit/wicket/panels/TextOption.html
@@ -7,7 +7,7 @@
<body>
<wicket:panel>
    <div style="padding-top:4px;">
        <div>
        <div style="margin-bottom:1px;">
            <b><span wicket:id="name"></span></b>
        </div>
        <label class="checkbox" style="color:#777;"> <span wicket:id="description"></span>