From c9921bd3b0b7bf90b6e5e2a52141c3fdf0f31f89 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 04 Jun 2014 17:04:17 -0400
Subject: [PATCH] Revise the user profile page and add a preferences form

---
 src/main/java/com/gitblit/wicket/panels/ChoiceOption.html        |    2 
 src/main/java/com/gitblit/wicket/pages/UserPage.html             |   51 ++++++++----
 src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html |    2 
 src/main/java/com/gitblit/wicket/panels/BooleanOption.html       |    2 
 src/main/java/com/gitblit/wicket/panels/TextOption.html          |    2 
 src/main/java/com/gitblit/wicket/pages/UserPage.java             |  153 ++++++++++++++++++++++++++++++++++---
 src/main/java/com/gitblit/wicket/GitBlitWebApp.properties        |    9 ++
 src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html   |    2 
 8 files changed, 185 insertions(+), 38 deletions(-)

diff --git a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties b/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
index d6fd57e..8117179 100644
--- a/src/main/java/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/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.
\ No newline at end of file
+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
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.html b/src/main/java/com/gitblit/wicket/pages/UserPage.html
index 7aaded7..0926787 100644
--- a/src/main/java/com/gitblit/wicket/pages/UserPage.html
+++ b/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>
\ No newline at end of file
diff --git a/src/main/java/com/gitblit/wicket/pages/UserPage.java b/src/main/java/com/gitblit/wicket/pages/UserPage.java
index 29b49b3..baad4a0 100644
--- a/src/main/java/com/gitblit/wicket/pages/UserPage.java
+++ b/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 +")";
+		}
+	}
 }
diff --git a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html b/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html
index 87a0206..0705019 100644
--- a/src/main/java/com/gitblit/wicket/panels/AccessPolicyPanel.html
+++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html
index fb360d1..b1ced8d 100644
--- a/src/main/java/com/gitblit/wicket/panels/BooleanChoiceOption.html
+++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/panels/BooleanOption.html b/src/main/java/com/gitblit/wicket/panels/BooleanOption.html
index 6684fe9..297cbd3 100644
--- a/src/main/java/com/gitblit/wicket/panels/BooleanOption.html
+++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html b/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html
index 8c34c81..e9e4887 100644
--- a/src/main/java/com/gitblit/wicket/panels/ChoiceOption.html
+++ b/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>
diff --git a/src/main/java/com/gitblit/wicket/panels/TextOption.html b/src/main/java/com/gitblit/wicket/panels/TextOption.html
index 9fa0c70..d14da2b 100644
--- a/src/main/java/com/gitblit/wicket/panels/TextOption.html
+++ b/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>

--
Gitblit v1.9.1