From 797322eb90a1f5d21166fd691479b050ad7b754b Mon Sep 17 00:00:00 2001 From: James Moger Date: Mon, 21 Nov 2011 09:24:05 -0500 Subject: [PATCH] Tighter Gravatar integration. New window/tab on most activity links. Each Gravatar thumbnail is now a link to the Gitblit Gravatar profile page. This page displays some of the profile information and contains a link to the full Gravatar profile. Activity page links now launch a new window/tab instead of targeting "self" since it can be expensive to requery the activity information. --- src/com/gitblit/models/GravatarProfile.java | 83 +++++++++++++++++++ src/com/gitblit/utils/ActivityUtils.java | 66 +++++++++++++++ src/com/gitblit/wicket/GitBlitWebApp.java | 4 +- src/com/gitblit/wicket/GravatarImage.java | 62 -------------- src/com/gitblit/wicket/pages/CommitPage.html | 4 +- src/com/gitblit/wicket/pages/CommitPage.java | 2 +- .../wicket/pages/GravatarProfilePage.html | 20 +++++ .../wicket/pages/GravatarProfilePage.java | 64 ++++++++++++++ .../gitblit/wicket/panels/ActivityPanel.html | 4 +- .../gitblit/wicket/panels/ActivityPanel.java | 11 ++- .../gitblit/wicket/panels/GravatarImage.html | 9 ++ .../gitblit/wicket/panels/GravatarImage.java | 68 +++++++++++++++ src/com/gitblit/wicket/panels/LinkPanel.java | 17 +++- tests/com/gitblit/tests/ActivityTest.java | 31 +++++++ 14 files changed, 369 insertions(+), 76 deletions(-) create mode 100644 src/com/gitblit/models/GravatarProfile.java delete mode 100644 src/com/gitblit/wicket/GravatarImage.java create mode 100644 src/com/gitblit/wicket/pages/GravatarProfilePage.html create mode 100644 src/com/gitblit/wicket/pages/GravatarProfilePage.java create mode 100644 src/com/gitblit/wicket/panels/GravatarImage.html create mode 100644 src/com/gitblit/wicket/panels/GravatarImage.java create mode 100644 tests/com/gitblit/tests/ActivityTest.java diff --git a/src/com/gitblit/models/GravatarProfile.java b/src/com/gitblit/models/GravatarProfile.java new file mode 100644 index 00000000..aa128ce0 --- /dev/null +++ b/src/com/gitblit/models/GravatarProfile.java @@ -0,0 +1,83 @@ +/* + * Copyright 2011 gitblit.com. + * + * 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.gitblit.models; + +import java.io.Serializable; +import java.util.List; + +/** + * Represents a Gravatar profile. + * + * @author James Moger + * + */ +public class GravatarProfile implements Serializable { + + private static final long serialVersionUID = 1L; + + public String id; + public String hash; + public String requestHash; + public String displayName; + public String preferredUsername; + public String currentLocation; + public String aboutMe; + + public String profileUrl; + public String thumbnailUrl; + public List photos; +// public Map profileBackground; +// public Map name; + + public List phoneNumbers; + public List emails; + public List ims; + public List accounts; + public List urls; + + public static class ProfileObject implements Serializable { + + private static final long serialVersionUID = 1L; + + public String title; + public String type; + public String value; + public boolean primary; + + @Override + public String toString() { + return value; + } + } + + public static class Account implements Serializable { + + private static final long serialVersionUID = 1L; + + public String domain; + public String display; + public String url; + public String username; + public String userid; + public boolean verified; + public String shortname; + + @Override + public String toString() { + return display; + } + } +} diff --git a/src/com/gitblit/utils/ActivityUtils.java b/src/com/gitblit/utils/ActivityUtils.java index 8c8a7ec2..204fe3c3 100644 --- a/src/com/gitblit/utils/ActivityUtils.java +++ b/src/com/gitblit/utils/ActivityUtils.java @@ -15,7 +15,11 @@ */ package com.gitblit.utils; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.Type; import java.text.DateFormat; +import java.text.MessageFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; @@ -33,8 +37,10 @@ import org.eclipse.jgit.revwalk.RevCommit; import com.gitblit.GitBlit; import com.gitblit.models.Activity; import com.gitblit.models.Activity.RepositoryCommit; +import com.gitblit.models.GravatarProfile; import com.gitblit.models.RefModel; import com.gitblit.models.RepositoryModel; +import com.google.gson.reflect.TypeToken; /** * Utility class for building activity information from repositories. @@ -127,4 +133,64 @@ public class ActivityUtils { } return recentActivity; } + + /** + * Returns the Gravatar profile, if available, for the specified email + * address. + * + * @param emailaddress + * @return a Gravatar Profile + * @throws IOException + */ + public static GravatarProfile getGravatarProfileFromAddress(String emailaddress) + throws IOException { + return getGravatarProfile(StringUtils.getMD5(emailaddress.toLowerCase())); + } + + /** + * Creates a Gravatar thumbnail url from the specified email address. + * + * @param email + * address to query Gravatar + * @param width + * size of thumbnail. if width <= 0, the defalt of 60 is used. + * @return + */ + public static String getGravatarThumbnailUrl(String email, int width) { + if (width <= 0) { + width = 60; + } + String emailHash = StringUtils.getMD5(email); + String url = MessageFormat.format( + "http://www.gravatar.com/avatar/{0}?s={1,number,0}&d=identicon", emailHash, width); + return url; + } + + /** + * Returns the Gravatar profile, if available, for the specified hashcode. + * address. + * + * @param hash + * the hash of the email address + * @return a Gravatar Profile + * @throws IOException + */ + public static GravatarProfile getGravatarProfile(String hash) throws IOException { + String url = MessageFormat.format("http://www.gravatar.com/{0}.json", hash); + // Gravatar has a complex json structure + Type profileType = new TypeToken>>() { + }.getType(); + Map> profiles = null; + try { + profiles = JsonUtils.retrieveJson(url, profileType); + } catch (FileNotFoundException e) { + } + if (profiles == null || profiles.size() == 0) { + return null; + } + // due to the complex json structure we need to pull out the profile + // from a list 2 levels deep + GravatarProfile profile = profiles.values().iterator().next().get(0); + return profile; + } } diff --git a/src/com/gitblit/wicket/GitBlitWebApp.java b/src/com/gitblit/wicket/GitBlitWebApp.java index 79083efb..e2391d6d 100644 --- a/src/com/gitblit/wicket/GitBlitWebApp.java +++ b/src/com/gitblit/wicket/GitBlitWebApp.java @@ -34,6 +34,7 @@ import com.gitblit.wicket.pages.CommitDiffPage; import com.gitblit.wicket.pages.CommitPage; import com.gitblit.wicket.pages.DocsPage; import com.gitblit.wicket.pages.FederationRegistrationPage; +import com.gitblit.wicket.pages.GravatarProfilePage; import com.gitblit.wicket.pages.HistoryPage; import com.gitblit.wicket.pages.LogPage; import com.gitblit.wicket.pages.MarkdownPage; @@ -104,8 +105,9 @@ public class GitBlitWebApp extends WebApplication { // federation urls mount("/proposal", ReviewProposalPage.class, "t"); mount("/registration", FederationRegistrationPage.class, "u", "n"); - + mount("/activity", ActivityPage.class, "r", "h"); + mount("/gravatar", GravatarProfilePage.class, "h"); } private void mount(String location, Class clazz, String... parameters) { diff --git a/src/com/gitblit/wicket/GravatarImage.java b/src/com/gitblit/wicket/GravatarImage.java deleted file mode 100644 index 88c97c93..00000000 --- a/src/com/gitblit/wicket/GravatarImage.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2011 gitblit.com. - * - * 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.gitblit.wicket; - -import java.text.MessageFormat; - -import org.apache.wicket.AttributeModifier; -import org.apache.wicket.markup.ComponentTag; -import org.apache.wicket.markup.html.WebComponent; -import org.apache.wicket.model.Model; -import org.eclipse.jgit.lib.PersonIdent; - -import com.gitblit.GitBlit; -import com.gitblit.Keys; -import com.gitblit.utils.StringUtils; - -/** - * Represents a Gravatar image. - * - * @author James Moger - * - */ -public class GravatarImage extends WebComponent { - - private static final long serialVersionUID = 1L; - - public GravatarImage(String id, PersonIdent person) { - this(id, person, 0); - } - - public GravatarImage(String id, PersonIdent person, int width) { - super(id); - if (width <= 0) { - width = 60; - } - String authorhash = StringUtils.getMD5(person.getEmailAddress().toLowerCase()); - String url = MessageFormat.format("http://www.gravatar.com/avatar/{0}?s={1,number,0}&d=identicon", authorhash, width); - add(new AttributeModifier("src", true, new Model(url))); - setVisible(GitBlit.getBoolean(Keys.web.allowGravatar, true)); - WicketUtils.setCssClass(this, "gravatar"); - } - - @Override - protected void onComponentTag(ComponentTag tag) { - super.onComponentTag(tag); - checkComponentTag(tag, "img"); - } - -} \ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/CommitPage.html b/src/com/gitblit/wicket/pages/CommitPage.html index 2af05e11..fd2c05c3 100644 --- a/src/com/gitblit/wicket/pages/CommitPage.html +++ b/src/com/gitblit/wicket/pages/CommitPage.html @@ -16,7 +16,7 @@
[commit header]
- + @@ -57,7 +57,7 @@
- + diff --git a/src/com/gitblit/wicket/pages/CommitPage.java b/src/com/gitblit/wicket/pages/CommitPage.java index bfe03f12..1fd2653b 100644 --- a/src/com/gitblit/wicket/pages/CommitPage.java +++ b/src/com/gitblit/wicket/pages/CommitPage.java @@ -38,10 +38,10 @@ import com.gitblit.Keys; import com.gitblit.models.GitNote; import com.gitblit.models.PathModel.PathChangeModel; import com.gitblit.utils.JGitUtils; -import com.gitblit.wicket.GravatarImage; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.panels.CommitHeaderPanel; import com.gitblit.wicket.panels.CommitLegendPanel; +import com.gitblit.wicket.panels.GravatarImage; import com.gitblit.wicket.panels.LinkPanel; import com.gitblit.wicket.panels.RefsPanel; diff --git a/src/com/gitblit/wicket/pages/GravatarProfilePage.html b/src/com/gitblit/wicket/pages/GravatarProfilePage.html new file mode 100644 index 00000000..1719d908 --- /dev/null +++ b/src/com/gitblit/wicket/pages/GravatarProfilePage.html @@ -0,0 +1,20 @@ + + + + + + +

+
+
+

+ Complete profile on Gravatar.com +

+
+ + \ No newline at end of file diff --git a/src/com/gitblit/wicket/pages/GravatarProfilePage.java b/src/com/gitblit/wicket/pages/GravatarProfilePage.java new file mode 100644 index 00000000..1d702a7e --- /dev/null +++ b/src/com/gitblit/wicket/pages/GravatarProfilePage.java @@ -0,0 +1,64 @@ +/* + * Copyright 2011 gitblit.com. + * + * 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.gitblit.wicket.pages; + +import java.io.IOException; +import java.text.MessageFormat; + +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.PageParameters; +import org.apache.wicket.markup.html.basic.Label; +import org.apache.wicket.markup.html.image.Image; +import org.apache.wicket.markup.html.link.ExternalLink; +import org.apache.wicket.model.Model; + +import com.gitblit.models.GravatarProfile; +import com.gitblit.utils.ActivityUtils; +import com.gitblit.wicket.WicketUtils; + +/** + * Gravatar Profile Page shows the Gravatar information, if available. + * + * @author James Moger + * + */ +public class GravatarProfilePage extends RootPage { + + public GravatarProfilePage(PageParameters params) { + super(); + setupPage("", ""); + String object = WicketUtils.getObject(params); + GravatarProfile profile = null; + try { + if (object.indexOf('@') > -1) { + profile = ActivityUtils.getGravatarProfileFromAddress(object); + } else { + profile = ActivityUtils.getGravatarProfile(object); + } + } catch (IOException e) { + error(MessageFormat.format("Failed to find Gravatar profile for {0}", object), e, true); + } + + add(new Label("displayName", profile.displayName)); + add(new Label("username", profile.preferredUsername)); + add(new Label("location", profile.currentLocation)); + add(new Label("aboutMe", profile.aboutMe)); + Image image = new Image("profileImage"); + image.add(new AttributeModifier("src", true, new Model(profile.thumbnailUrl + "?s=256&d=identicon"))); + add(image); + add(new ExternalLink("profileLink", profile.profileUrl)); + } +} diff --git a/src/com/gitblit/wicket/panels/ActivityPanel.html b/src/com/gitblit/wicket/panels/ActivityPanel.html index 668e7c90..90e808ff 100644 --- a/src/com/gitblit/wicket/panels/ActivityPanel.html +++ b/src/com/gitblit/wicket/panels/ActivityPanel.html @@ -19,7 +19,7 @@ [repository link] - + [shortlog commit link]
@@ -30,7 +30,7 @@ - | | + | | diff --git a/src/com/gitblit/wicket/panels/ActivityPanel.java b/src/com/gitblit/wicket/panels/ActivityPanel.java index e9ec0741..80621ae4 100644 --- a/src/com/gitblit/wicket/panels/ActivityPanel.java +++ b/src/com/gitblit/wicket/panels/ActivityPanel.java @@ -29,7 +29,6 @@ import com.gitblit.models.Activity; import com.gitblit.models.Activity.RepositoryCommit; import com.gitblit.utils.StringUtils; import com.gitblit.wicket.GitBlitWebSession; -import com.gitblit.wicket.GravatarImage; import com.gitblit.wicket.WicketUtils; import com.gitblit.wicket.pages.CommitDiffPage; import com.gitblit.wicket.pages.CommitPage; @@ -90,27 +89,27 @@ public class ActivityPanel extends BasePanel { String author = commit.getAuthorIdent().getName(); LinkPanel authorLink = new LinkPanel("author", "list", author, SearchPage.class, WicketUtils.newSearchParameter(commit.repository, - commit.getName(), author, Constants.SearchType.AUTHOR)); + commit.getName(), author, Constants.SearchType.AUTHOR), true); setPersonSearchTooltip(authorLink, author, Constants.SearchType.AUTHOR); fragment.add(authorLink); // repository LinkPanel repositoryLink = new LinkPanel("repository", null, commit.repository, SummaryPage.class, - WicketUtils.newRepositoryParameter(commit.repository)); + WicketUtils.newRepositoryParameter(commit.repository), true); WicketUtils.setCssBackground(repositoryLink, commit.repository); fragment.add(repositoryLink); // repository branch LinkPanel branchLink = new LinkPanel("branch", "list", commit.branch, LogPage.class, WicketUtils.newObjectParameter(commit.repository, - commit.branch)); + commit.branch), true); WicketUtils.setCssStyle(branchLink, "color: #008000;"); fragment.add(branchLink); LinkPanel commitid = new LinkPanel("commitid", "list subject", commit.getShortName(), CommitPage.class, - WicketUtils.newObjectParameter(commit.repository, commit.getName())); + WicketUtils.newObjectParameter(commit.repository, commit.getName()), true); fragment.add(commitid); // message/commit link @@ -118,7 +117,7 @@ public class ActivityPanel extends BasePanel { String trimmedMessage = StringUtils.trimShortLog(shortMessage); LinkPanel shortlog = new LinkPanel("message", "list subject", trimmedMessage, CommitPage.class, WicketUtils.newObjectParameter( - commit.repository, commit.getName())); + commit.repository, commit.getName()), true); if (!shortMessage.equals(trimmedMessage)) { WicketUtils.setHtmlTooltip(shortlog, shortMessage); } diff --git a/src/com/gitblit/wicket/panels/GravatarImage.html b/src/com/gitblit/wicket/panels/GravatarImage.html new file mode 100644 index 00000000..9dda7958 --- /dev/null +++ b/src/com/gitblit/wicket/panels/GravatarImage.html @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/GravatarImage.java b/src/com/gitblit/wicket/panels/GravatarImage.java new file mode 100644 index 00000000..0dc05021 --- /dev/null +++ b/src/com/gitblit/wicket/panels/GravatarImage.java @@ -0,0 +1,68 @@ +/* + * Copyright 2011 gitblit.com. + * + * 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.gitblit.wicket.panels; + +import java.text.MessageFormat; + +import org.apache.wicket.AttributeModifier; +import org.apache.wicket.behavior.SimpleAttributeModifier; +import org.apache.wicket.markup.html.image.Image; +import org.apache.wicket.markup.html.link.BookmarkablePageLink; +import org.apache.wicket.markup.html.link.Link; +import org.apache.wicket.markup.html.panel.Panel; +import org.apache.wicket.model.Model; +import org.eclipse.jgit.lib.PersonIdent; + +import com.gitblit.GitBlit; +import com.gitblit.Keys; +import com.gitblit.utils.ActivityUtils; +import com.gitblit.utils.StringUtils; +import com.gitblit.wicket.WicketUtils; +import com.gitblit.wicket.pages.GravatarProfilePage; + +/** + * Represents a Gravatar image and links to the Gravatar profile page. + * + * @author James Moger + * + */ +public class GravatarImage extends Panel { + + private static final long serialVersionUID = 1L; + + public GravatarImage(String id, PersonIdent person) { + this(id, person, 0); + } + + public GravatarImage(String id, PersonIdent person, int width) { + super(id); + + String email = person.getEmailAddress().toLowerCase(); + String hash = StringUtils.getMD5(email); + Link link = new BookmarkablePageLink("link", GravatarProfilePage.class, + WicketUtils.newObjectParameter(hash)); + link.add(new SimpleAttributeModifier("target", "_blank")); + String url = ActivityUtils.getGravatarThumbnailUrl(email, width); + Image image = new Image("image"); + image.add(new AttributeModifier("src", true, new Model(url))); + WicketUtils.setCssClass(image, "gravatar"); + link.add(image); + WicketUtils.setHtmlTooltip(link, + MessageFormat.format("View Gravatar profile for {0}", person.getName())); + add(link); + setVisible(GitBlit.getBoolean(Keys.web.allowGravatar, true)); + } +} \ No newline at end of file diff --git a/src/com/gitblit/wicket/panels/LinkPanel.java b/src/com/gitblit/wicket/panels/LinkPanel.java index 475a71ef..2872d4bf 100644 --- a/src/com/gitblit/wicket/panels/LinkPanel.java +++ b/src/com/gitblit/wicket/panels/LinkPanel.java @@ -33,16 +33,26 @@ public class LinkPanel extends Panel { public LinkPanel(String wicketId, String linkCssClass, String label, Class clazz) { - this(wicketId, linkCssClass, new Model(label), clazz, null); + this(wicketId, linkCssClass, new Model(label), clazz, null, false); } public LinkPanel(String wicketId, String linkCssClass, String label, Class clazz, PageParameters parameters) { - this(wicketId, linkCssClass, new Model(label), clazz, parameters); + this(wicketId, linkCssClass, new Model(label), clazz, parameters, false); + } + + public LinkPanel(String wicketId, String linkCssClass, String label, + Class clazz, PageParameters parameters, boolean newWindow) { + this(wicketId, linkCssClass, new Model(label), clazz, parameters, newWindow); } public LinkPanel(String wicketId, String linkCssClass, IModel model, Class clazz, PageParameters parameters) { + this(wicketId, linkCssClass, model, clazz, parameters, false); + } + + public LinkPanel(String wicketId, String linkCssClass, IModel model, + Class clazz, PageParameters parameters, boolean newWindow) { super(wicketId); this.labelModel = model; Link link = null; @@ -51,6 +61,9 @@ public class LinkPanel extends Panel { } else { link = new BookmarkablePageLink("link", clazz, parameters); } + if (newWindow) { + link.add(new SimpleAttributeModifier("target", "_blank")); + } if (linkCssClass != null) { link.add(new SimpleAttributeModifier("class", linkCssClass)); } diff --git a/tests/com/gitblit/tests/ActivityTest.java b/tests/com/gitblit/tests/ActivityTest.java new file mode 100644 index 00000000..b7e5f7a1 --- /dev/null +++ b/tests/com/gitblit/tests/ActivityTest.java @@ -0,0 +1,31 @@ +/* + * Copyright 2011 gitblit.com. + * + * 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.gitblit.tests; + +import java.io.IOException; + +import junit.framework.TestCase; + +import com.gitblit.models.GravatarProfile; +import com.gitblit.utils.ActivityUtils; + +public class ActivityTest extends TestCase { + + public void testGravatarProfile() throws IOException { + GravatarProfile profile = ActivityUtils.getGravatarProfile("beau@dentedreality.com.au"); + assertEquals("beau", profile.preferredUsername); + } +} \ No newline at end of file -- 2.39.5