From faa32cdb4187155e42848a887df62aa104bf3a73 Mon Sep 17 00:00:00 2001 From: Massimiliano Assante Date: Wed, 8 May 2013 16:16:43 +0000 Subject: [PATCH] git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/social-profile@74741 82a268e6-3cf1-43bd-a215-b396298e98cf --- pom.xml | 6 ++ .../socialprofile/client/SocialService.java | 4 +- .../client/SocialServiceAsync.java | 4 + .../client/ui/DisplayProfile.java | 30 ++++++- .../client/ui/DisplayProfile.ui.xml | 11 +-- .../server/SocialServiceImpl.java | 80 +++++++++++++++++- .../socialprofile/shared/FieldVerifier.java | 42 --------- .../socialprofile/shared/UserSettings.java | 56 ++++++++++++ .../user/socialprofile/SocialProfile.gwt.xml | 21 +++-- src/main/webapp/SocialProfile.css | 28 ++++++ src/main/webapp/images/Avatar_default.png | Bin 0 -> 997 bytes src/main/webapp/images/avatarLoader.gif | Bin 0 -> 5215 bytes src/main/webapp/images/vre_bg_gray.png | Bin 0 -> 2814 bytes 13 files changed, 222 insertions(+), 60 deletions(-) delete mode 100644 src/main/java/org/gcube/portlets/user/socialprofile/shared/FieldVerifier.java create mode 100644 src/main/java/org/gcube/portlets/user/socialprofile/shared/UserSettings.java create mode 100644 src/main/webapp/images/Avatar_default.png create mode 100644 src/main/webapp/images/avatarLoader.gif create mode 100644 src/main/webapp/images/vre_bg_gray.png diff --git a/pom.xml b/pom.xml index e1e50ab..83984b6 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,12 @@ [1.4.0,1.6.0] provided + + org.gcube.portlets.user + gcube-widgets + [1.4.0-SNAPSHOT, 2.0.0-SNAPSHOT) + provided + org.gcube.portal custom-portal-handler diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialService.java b/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialService.java index 874eb85..6f12307 100644 --- a/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialService.java +++ b/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialService.java @@ -1,5 +1,7 @@ package org.gcube.portlets.user.socialprofile.client; +import org.gcube.portal.databook.shared.UserInfo; + import com.google.gwt.user.client.rpc.RemoteService; import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @@ -8,5 +10,5 @@ import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; */ @RemoteServiceRelativePath("greet") public interface SocialService extends RemoteService { - + UserInfo getUserInfo(); } diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialServiceAsync.java b/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialServiceAsync.java index 5fd7918..87a9196 100644 --- a/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialServiceAsync.java +++ b/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialServiceAsync.java @@ -1,7 +1,11 @@ package org.gcube.portlets.user.socialprofile.client; +import org.gcube.portal.databook.shared.UserInfo; + import com.google.gwt.user.client.rpc.AsyncCallback; public interface SocialServiceAsync { + + void getUserInfo(AsyncCallback callback); } diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.java b/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.java index 882329d..e741969 100644 --- a/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.java +++ b/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.java @@ -1,12 +1,15 @@ package org.gcube.portlets.user.socialprofile.client.ui; +import org.gcube.portal.databook.shared.UserInfo; import org.gcube.portlets.user.socialprofile.client.SocialService; import org.gcube.portlets.user.socialprofile.client.SocialServiceAsync; import com.google.gwt.core.client.GWT; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.rpc.AsyncCallback; import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.Widget; @@ -17,13 +20,38 @@ public class DisplayProfile extends Composite { interface DisplayProfileUiBinder extends UiBinder { } - + public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png"; + public static final String loading = GWT.getModuleBaseURL() + "../images/avatarLoader.gif"; + private final SocialServiceAsync socialService = GWT.create(SocialService.class); + @UiField HTMLPanel mainPanel; @UiField Image avatarImage; + + private UserInfo myUserInfo; + public DisplayProfile() { initWidget(uiBinder.createAndBindUi(this)); + avatarImage.setUrl(loading); + mainPanel.addStyleName("framed"); + + socialService.getUserInfo(new AsyncCallback() { + + @Override + public void onSuccess(UserInfo result) { + myUserInfo = result; + avatarImage.getElement().getParentElement().setAttribute("href", myUserInfo.getAccountURL()); + avatarImage.setSize("60px", "60px"); + avatarImage.setUrl(myUserInfo.getAvatarId()); + } + + @Override + public void onFailure(Throwable caught) { + avatarImage.setSize("120px", "120px"); + avatarImage.setUrl(avatar_default); + } + }); } } diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.ui.xml b/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.ui.xml index 596e5b8..eba542a 100644 --- a/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.ui.xml +++ b/src/main/java/org/gcube/portlets/user/socialprofile/client/ui/DisplayProfile.ui.xml @@ -1,19 +1,20 @@ - + - diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/server/SocialServiceImpl.java b/src/main/java/org/gcube/portlets/user/socialprofile/server/SocialServiceImpl.java index 046d66b..fbf542e 100644 --- a/src/main/java/org/gcube/portlets/user/socialprofile/server/SocialServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/socialprofile/server/SocialServiceImpl.java @@ -1,14 +1,90 @@ package org.gcube.portlets.user.socialprofile.server; +import java.util.HashMap; + +import org.gcube.application.framework.core.session.ASLSession; +import org.gcube.application.framework.core.session.SessionManager; +import org.gcube.common.core.utils.logging.GCUBEClientLog; +import org.gcube.portal.custom.communitymanager.OrganizationsUtil; +import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper; +import org.gcube.portal.databook.shared.UserInfo; import org.gcube.portlets.user.socialprofile.client.SocialService; -import org.gcube.portlets.user.socialprofile.shared.FieldVerifier; + import com.google.gwt.user.server.rpc.RemoteServiceServlet; +import com.liferay.portal.kernel.util.WebKeys; +import com.liferay.portal.service.UserLocalServiceUtil; +import com.liferay.portal.theme.ThemeDisplay; /** * The server side implementation of the RPC service. */ @SuppressWarnings("serial") public class SocialServiceImpl extends RemoteServiceServlet implements SocialService { + /** + * + */ + private static GCUBEClientLog _log = new GCUBEClientLog(SocialServiceImpl.class); + + /** + * used for debugging in eclipse + */ + private boolean withinPortal = false; + + /** + * the current ASLSession + * @return the session + */ + private ASLSession getASLSession() { + String sessionID = this.getThreadLocalRequest().getSession().getId(); + String user = (String) this.getThreadLocalRequest().getSession().getAttribute(ScopeHelper.USERNAME_ATTRIBUTE); + if (user == null) { + _log.warn("USER IS NULL setting test.user and Running OUTSIDE PORTAL"); + user = "test.user"; +// user = "massimiliano.assante"; +// SessionManager.getInstance().getASLSession(sessionID, user).setScope("/gcube/devsec/devVRE"); + withinPortal = false; + } + else { + withinPortal = true; + } + return SessionManager.getInstance().getASLSession(sessionID, user); + } + + @Override + public UserInfo getUserInfo() { + try { + ASLSession session = getASLSession(); + String username = session.getUsername(); + String email = username+"@isti.cnr.it"; + String fullName = username+" FULL"; + String thumbnailURL = "images/Avatar_default.png"; - + if (withinPortal) { + + com.liferay.portal.model.UserModel user = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), username); + thumbnailURL = "/image/user_male_portrait?img_id="+user.getPortraitId(); + fullName = user.getFirstName() + " " + user.getLastName(); + email = user.getEmailAddress(); + ThemeDisplay themeDisplay = (ThemeDisplay) this.getThreadLocalRequest().getSession().getAttribute(WebKeys.THEME_DISPLAY); + String accountURL = themeDisplay.getURLMyAccount().toString(); + HashMap vreNames = new HashMap(); + + UserInfo userInfo = new UserInfo(username, fullName, thumbnailURL, user.getEmailAddress(), accountURL, true, false, vreNames); + return userInfo; + } + else { + _log.info("Returning test USER"); + HashMap fakeVreNames = new HashMap(); + fakeVreNames.put("/gcube/devsec/devVRE","devVRE"); + //fakeVreNames.put("/gcube/devNext/NexNext","NexNext"); + + UserInfo user = new UserInfo(getASLSession().getUsername(), fullName, thumbnailURL, email, "fakeAccountUrl", true, false, fakeVreNames); + return (user); + } + + } catch (Exception e) { + e.printStackTrace(); + } + return new UserInfo(); + } } diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/shared/FieldVerifier.java b/src/main/java/org/gcube/portlets/user/socialprofile/shared/FieldVerifier.java deleted file mode 100644 index a2ebb57..0000000 --- a/src/main/java/org/gcube/portlets/user/socialprofile/shared/FieldVerifier.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.gcube.portlets.user.socialprofile.shared; - -/** - *

- * FieldVerifier validates that the name the user enters is valid. - *

- *

- * This class is in the shared packing because we use it in both - * the client code and on the server. On the client, we verify that the name is - * valid before sending an RPC request so the user doesn't have to wait for a - * network round trip to get feedback. On the server, we verify that the name is - * correct to ensure that the input is correct regardless of where the RPC - * originates. - *

- *

- * When creating a class that is used on both the client and the server, be sure - * that all code is translatable and does not use native JavaScript. Code that - * is note translatable (such as code that interacts with a database or the file - * system) cannot be compiled into client side JavaScript. Code that uses native - * JavaScript (such as Widgets) cannot be run on the server. - *

- */ -public class FieldVerifier { - - /** - * Verifies that the specified name is valid for our service. - * - * In this example, we only require that the name is at least four - * characters. In your application, you can use more complex checks to ensure - * that usernames, passwords, email addresses, URLs, and other fields have the - * proper syntax. - * - * @param name the name to validate - * @return true if valid, false if invalid - */ - public static boolean isValidName(String name) { - if (name == null) { - return false; - } - return name.length() > 3; - } -} diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/shared/UserSettings.java b/src/main/java/org/gcube/portlets/user/socialprofile/shared/UserSettings.java new file mode 100644 index 0000000..de520f7 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/socialprofile/shared/UserSettings.java @@ -0,0 +1,56 @@ +package org.gcube.portlets.user.socialprofile.shared; + +import java.io.Serializable; + +import org.gcube.portal.databook.shared.UserInfo; + +@SuppressWarnings("serial") +public class UserSettings implements Serializable { + private UserInfo userInfo; + private int refreshingTimeInMillis; + private String currentScope; + boolean isInfrastructure; + public UserSettings() { + super(); + } + public UserSettings(UserInfo userInfo, int refreshingTimeInMillis, + String currentScope, boolean isInfrastructure) { + super(); + this.userInfo = userInfo; + this.refreshingTimeInMillis = refreshingTimeInMillis; + this.currentScope = currentScope; + this.isInfrastructure = isInfrastructure; + } + public UserInfo getUserInfo() { + return userInfo; + } + public void setUserInfo(UserInfo userInfo) { + this.userInfo = userInfo; + } + public int getRefreshingTimeInMillis() { + return refreshingTimeInMillis; + } + public void setRefreshingTimeInMillis(int refreshingTimeInMillis) { + this.refreshingTimeInMillis = refreshingTimeInMillis; + } + public String getCurrentScope() { + return currentScope; + } + public void setCurrentScope(String currentScope) { + this.currentScope = currentScope; + } + public boolean isInfrastructure() { + return isInfrastructure; + } + public void setInfrastructure(boolean isInfrastructure) { + this.isInfrastructure = isInfrastructure; + } + @Override + public String toString() { + return "UserSettings [userInfo=" + userInfo + + ", refreshingTimeInMillis=" + refreshingTimeInMillis + + ", currentScope=" + currentScope + ", isInfrastructure=" + + isInfrastructure + "]"; + } + +} diff --git a/src/main/resources/org/gcube/portlets/user/socialprofile/SocialProfile.gwt.xml b/src/main/resources/org/gcube/portlets/user/socialprofile/SocialProfile.gwt.xml index ec47f27..c6b033c 100644 --- a/src/main/resources/org/gcube/portlets/user/socialprofile/SocialProfile.gwt.xml +++ b/src/main/resources/org/gcube/portlets/user/socialprofile/SocialProfile.gwt.xml @@ -1,15 +1,18 @@ - - + + - + + + + + + - - - - - - + + + diff --git a/src/main/webapp/SocialProfile.css b/src/main/webapp/SocialProfile.css index e69de29..423d0fb 100644 --- a/src/main/webapp/SocialProfile.css +++ b/src/main/webapp/SocialProfile.css @@ -0,0 +1,28 @@ +.framed { + margin: 0 0 10px; + padding: 10px; + margin: 0px 5px; + background: #FFF url(images/vre_bg_gray.png) repeat-x left bottom; + border-radius: 6px !important; + -moz-border-radius: 6px !important; + -webkit-border-radius: 6px !important; + border: 1px solid #DBDBDB; +} + +.user-photo { + display: block; + padding: 2px; + border: 1px solid #E6E6E6; +} + +.full-name { + font-family: Helvetica, Arial, sans-serif; + font-size: 24px; + font-weight: bold; +} + +.headline { + font-family: Helvetica, Arial, sans-serif; + font-size: 16px; + color: red; +} \ No newline at end of file diff --git a/src/main/webapp/images/Avatar_default.png b/src/main/webapp/images/Avatar_default.png new file mode 100644 index 0000000000000000000000000000000000000000..2a6c84458afa00029a1d5e6b96cc3f0237b4f745 GIT binary patch literal 997 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 literal 0 HcmV?d00001 diff --git a/src/main/webapp/images/vre_bg_gray.png b/src/main/webapp/images/vre_bg_gray.png new file mode 100644 index 0000000000000000000000000000000000000000..31cb9233e6f38a89528452b6be238c580992ae7d GIT binary patch literal 2814 zcmVKLZ*U+IBfRsybQWXdwQbLP>6pAqfylh#{fb6;Z(vMMVS~$e@S=j*ftg6;Uhf59&ghTmgWD0l;*T zI709Y^p6lP1rIRMx#05C~cW=H_Aw*bJ-5DT&Z2n+x)QHX^p z00esgV8|mQcmRZ%02D^@S3L16t`O%c004NIvOKvYIYoh62rY33S640`D9%Y2D-rV&neh&#Q1i z007~1e$oCcFS8neI|hJl{-P!B1ZZ9hpmq0)X0i`JwE&>$+E?>%_LC6RbVIkUx0b+_+BaR3cnT7Zv!AJxW zizFb)h!jyGOOZ85F;a?DAXP{m@;!0_IfqH8(HlgRxt7s3}k3K`kFu>>-2Q$QMFfPW!La{h336o>X zu_CMttHv6zR;&ZNiS=X8v3CR#fknUxHUxJ0uoBa_M6WNWeqIg~6QE69c9o#eyhGvpiOA@W-aonk<7r1(?fC{oI5N*U!4 zfg=2N-7=cNnjjOr{yriy6mMFgG#l znCF=fnQv8CDz++o6_Lscl}eQ+l^ZHARH>?_s@|##Rr6KLRFA1%Q+=*RRWnoLsR`7U zt5vFIcfW3@?wFpwUVxrVZ>QdQz32KIeJ}k~{cZZE^+ya? z2D1z#2HOnI7(B%_ac?{wFUQ;QQA1tBKtrWrm0_3Rgps+?Jfqb{jYbcQX~taRB;#$y zZN{S}1|}gUOHJxc?wV3fxuz+mJ4`!F$IZ;mqRrNsHJd##*D~ju=bP7?-?v~|cv>vB zsJ6IeNwVZxrdjT`yl#bBIa#GxRa#xMMy;K#CDyyGyQdMSxlWT#tDe?p!?5wT$+oGt z8L;Kp2HUQ-ZMJ=3XJQv;x5ci*?vuTfeY$;({XGW_huIFR9a(?@3)XSs8O^N5RyOM=TTmp(3=8^+zpz2r)C z^>JO{deZfso3oq3?Wo(Y?l$ge?uXo;%ru`Vo>?<<(8I_>;8Eq#KMS9gFl*neeosSB zfoHYnBQIkwkyowPu(zdms`p{<7e4kra-ZWq<2*OsGTvEV%s0Td$hXT+!*8Bnh2KMe zBmZRodjHV?r+_5^X9J0WL4jKW`}lf%A-|44I@@LTvf1rHjG(ze6+w@Jt%Bvjts!X0 z?2xS?_ve_-kiKB_KiJlZ$9G`c^=E@oNG)mWWaNo-3TIW8)$Hg0Ub-~8?KhvJ>$ z3*&nim@mj(aCxE5!t{lw7O5^0EIO7zOo&c6l<+|iDySBWCGrz@C5{St!X3hAA}`T4 z(TLbXTq+(;@<=L8dXnssyft|w#WSTW<++3>sgS%(4NTpeI-VAqb|7ssJvzNHgOZVu zaYCvgO_R1~>SyL=cFU|~g|hy|Zi}}s9+d~lYqOB71z9Z$wnC=pR9Yz4DhIM>Wmjgu z&56o6maCpC&F##y%G;1PobR9i?GnNg;gYtchD%p19a!eQtZF&3JaKv33gZ<8D~47E ztUS1iwkmDaPpj=$m#%)jCVEY4fnLGNg2A-`YwHVD3gv};>)hAvT~AmqS>Lr``i7kw zJ{5_It`yrBmlc25DBO7E8;5VoznR>Ww5hAaxn$2~(q`%A-YuS64wkBy=9dm`4cXeX z4c}I@?e+FW+b@^RDBHV(wnMq2zdX3SWv9u`%{xC-q*U}&`cyXV(%rRT*Z6MH?i+i& z_B8C(+grT%{XWUQ+f@NoP1R=AW&26{v-dx)iK^-Nmiuj8txj!m?Z*Ss1N{dh4z}01 z)YTo*JycSU)+_5r4#yw9{+;i4Ee$peRgIj+;v;ZGdF1K$3E%e~4LaI(jC-u%2h$&R z9cLXcYC@Xwnns&bn)_Q~Te?roKGD|d-g^8;+aC{{G(1^(O7m37Y1-+6)01cN&y1aw zoqc{T`P^XJqPBbIW6s}d4{z_f5Om?vMgNQEJG?v2T=KYd^0M3I6IZxbny)%vZR&LD zJpPl@Psh8QyPB@KTx+@RdcC!KX7}kEo;S|j^u2lU7XQ}Oo;f|;z4Ll+_r>@1-xl3| zawq-H%e&ckC+@AhPrP6BKT#_XdT7&;F71j}Joy zkC~6lh7E@6o;W@^IpRNZ{ptLtL(gQ-CY~4mqW;US7Zxvm_|@yz&e53Bp_lTPlfP|z zrTyx_>lv@x#=^!PzR7qqF<$gm`|ZJZ+;<)Cqu&ot2z=0000WV@Og>004R=004l4008;_004mL004C`008P>0026e000+nl3&F} z0000fNkl|9|twlOQeLhM{eM0J)y`{`BvFsO!};0AM3H`ggq` Q*Z=?k07*qoM6N<$f<6d3xBvhE literal 0 HcmV?d00001
- + +
- SSSSSS +
Massimiliano Assante
+
Researcher