diff --git a/pom.xml b/pom.xml index bc92161..8f4828d 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,7 @@ [1.4.0,1.6.0] provided + org.gcube.portlets.user gcube-widgets diff --git a/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialProfile.java b/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialProfile.java index 565944b..bcea4cd 100644 --- a/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialProfile.java +++ b/src/main/java/org/gcube/portlets/user/socialprofile/client/SocialProfile.java @@ -10,10 +10,10 @@ import com.google.gwt.user.client.ui.RootPanel; */ public class SocialProfile implements EntryPoint { - /** - * This is the entry point method. - */ - public void onModuleLoad() { - RootPanel.get("SocialProfileDiv").add(new DisplayProfile()); - } + /** + * This is the entry point method. + */ + public void onModuleLoad() { + RootPanel.get("SocialProfileDiv").add(new DisplayProfile()); + } } 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 90ebb56..cad7057 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 @@ -11,4 +11,8 @@ import com.google.gwt.user.client.rpc.RemoteServiceRelativePath; @RemoteServiceRelativePath("socialService") public interface SocialService extends RemoteService { UserContext getUserContext(String userid); + + Boolean saveHeadline(String newHeadline); + + Boolean saveIsti(String institution); } 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 d7ac65f..2137292 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 @@ -7,5 +7,9 @@ import com.google.gwt.user.client.rpc.AsyncCallback; public interface SocialServiceAsync { void getUserContext(String userid, AsyncCallback callback); + + void saveHeadline(String newHeadline, AsyncCallback callback); + + void saveIsti(String institution, 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 b8f360d..0a98333 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 @@ -6,18 +6,26 @@ import org.gcube.portlets.user.socialprofile.client.SocialServiceAsync; import org.gcube.portlets.user.socialprofile.shared.UserContext; import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.user.client.Window; import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.Button; import com.google.gwt.user.client.ui.Composite; import com.google.gwt.user.client.ui.HTML; import com.google.gwt.user.client.ui.HTMLPanel; import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.TextBox; import com.google.gwt.user.client.ui.Widget; public class DisplayProfile extends Composite { - + protected final static String HEADLINE_TEXT = "Professional Headline"; + protected final static String HEADLINE_ERROR = "Your Headline please"; + protected final static String ISTI_TEXT = "Company"; + private static DisplayProfileUiBinder uiBinder = GWT .create(DisplayProfileUiBinder.class); @@ -25,44 +33,146 @@ public class DisplayProfile extends Composite { } public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png"; public static final String loading = GWT.getModuleBaseURL() + "../images/avatarLoader.gif"; + public static final String savingImage = GWT.getModuleBaseURL() + "../images/saving.gif"; public static final String GET_OID_PARAMETER = "oid"; private final SocialServiceAsync socialService = GWT.create(SocialService.class); @UiField HTMLPanel mainPanel; @UiField Image avatarImage; @UiField HTML userFullName; - @UiField HTML headline; - @UiField HTML institution; + @UiField TextBox headline; + @UiField TextBox institution; + + @UiField HTML editHeadline; + @UiField HTML editIsti; + + @UiField Image savingHeadline; + @UiField Button saveHead; + @UiField Button cancelHead; + @UiField Button messageButton; + private String currHeadLine; + private UserInfo myUserInfo; public DisplayProfile() { initWidget(uiBinder.createAndBindUi(this)); avatarImage.setUrl(loading); - mainPanel.addStyleName("framed"); - - if (getUserToShowId() == null) { //its him seeing himself - socialService.getUserContext(null, new AsyncCallback() { - @Override - public void onSuccess(UserContext result) { - myUserInfo = result.getUserInfo(); - avatarImage.getElement().getParentElement().setAttribute("href", myUserInfo.getAccountURL()); - avatarImage.setSize("100px", "100px"); - avatarImage.setUrl(myUserInfo.getAvatarId()); - userFullName.setText(myUserInfo.getFullName()); - headline.setText(result.getHeadline()); - institution.setText(result.getInstitution()); - } - @Override - public void onFailure(Throwable caught) { - Window.alert("Failure: " + caught.getMessage()); - avatarImage.setSize("100px", "100px"); - avatarImage.setUrl(avatar_default); - } - }); - } else { + mainPanel.addStyleName("framed"); + savingHeadline.setUrl(savingImage); + socialService.getUserContext(getUserToShowId(), new AsyncCallback() { + @Override + public void onSuccess(UserContext result) { + myUserInfo = result.getUserInfo(); + avatarImage.getElement().getParentElement().setAttribute("href", myUserInfo.getAccountURL()); + avatarImage.setSize("100px", "100px"); + avatarImage.setUrl(myUserInfo.getAvatarId()); + userFullName.setText(myUserInfo.getFullName()); - } + if (getUserToShowId() == null) { //its him seeing his profile + + String head = (result.getHeadline() == null || result.getHeadline().compareTo("") == 0) ? HEADLINE_TEXT : result.getHeadline(); + String isti = (result.getInstitution() == null ||result.getInstitution().compareTo("") == 0) ? ISTI_TEXT : result.getInstitution(); + headline.setText(head); + institution.setText(isti); + + editHeadline.setStyleName("editImage"); + editHeadline.setTitle("Edit your Professional Headline"); + headline.setMaxLength(35); + + editIsti.setStyleName("editImage"); + editIsti.setTitle("Edit your Company"); + + messageButton.removeFromParent(); + currHeadLine = head; + if (result.getHeadline() == null || result.getHeadline().compareTo("") == 0) { + headline.getElement().getStyle().setOpacity(0.5); + institution.getElement().getStyle().setOpacity(0.5); + headline.getElement().getStyle().setWidth(270, Unit.PX); + institution.getElement().getStyle().setWidth(270, Unit.PX); + } + } else { //its someone else + String head = (result.getHeadline() == null || result.getHeadline().compareTo("") == 0) ? "" : result.getHeadline(); + String isti = (result.getInstitution() == null || result.getInstitution().compareTo("") == 0) ? "" : result.getInstitution(); + headline.setText(head); + institution.setText(isti); + + avatarImage.getElement().getParentElement().setAttribute("href", ""); + avatarImage.setTitle(myUserInfo.getFullName()); + messageButton.setText("Private Message"); + messageButton.setVisible(true); + } + + + } + @Override + public void onFailure(Throwable caught) { + Window.alert("Failure: " + caught.getMessage()); + avatarImage.setSize("100px", "100px"); + avatarImage.setUrl(avatar_default); + } + }); + + editHeadline.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + headline.addStyleName("edit"); + headline.setReadOnly(false); + headline.setFocus(true); + headline.selectAll(); + editHeadline.setVisible(false); + saveHead.setVisible(true); + cancelHead.setVisible(true); + } + }); + + saveHead.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + String toShare = escapeHtml(headline.getText()); + if (toShare.equals("") || toShare.equals(HEADLINE_TEXT) || toShare.equals(HEADLINE_ERROR)) { + headline.setText(HEADLINE_ERROR); + } else { + currHeadLine = toShare; + saveHead.setVisible(false); + cancelHead.setVisible(false); + savingHeadline.setVisible(true); + headline.setReadOnly(true); + socialService.saveHeadline(currHeadLine, new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Window.alert("Sorry, an error occurred"); + cancelHeadline(); + } + + @Override + public void onSuccess(Boolean result) { + headline.removeStyleName("edit"); + editHeadline.setVisible(true); + headline.getElement().getStyle().setOpacity(1.0); + } + }); + + } + } + }); + + cancelHead.addClickHandler(new ClickHandler() { + @Override + public void onClick(ClickEvent event) { + cancelHeadline(); + } + }); + } + + private void cancelHeadline() { + headline.removeStyleName("edit"); + headline.setReadOnly(true); + editHeadline.setVisible(true); + saveHead.setVisible(false); + cancelHead.setVisible(false); + headline.setText(currHeadLine); } /** * check if it has to show just one feed @@ -71,4 +181,19 @@ public class DisplayProfile extends Composite { private String getUserToShowId() { return Window.Location.getParameter(GET_OID_PARAMETER); } + + /** + * Escape an html string. Escaping data received from the client helps to + * prevent cross-site script vulnerabilities. + * + * @param html the html string to escape + * @return the escaped string + */ + private String escapeHtml(String html) { + if (html == null) { + return null; + } + return html.replaceAll("&", "&").replaceAll("<", "<") + .replaceAll(">", ">"); + } } 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 1d3c1db..5de82e0 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 @@ -11,11 +11,38 @@ - +
- - + + + + + + + + + + + +
+ + + Save + Cancel + + +
+ + + + +
+
+
+
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 77ef281..8362a1b 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 @@ -10,6 +10,11 @@ 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.UserContext; +import org.gcube.vomanagement.usermanagement.UserManager; +import org.gcube.vomanagement.usermanagement.exception.UserManagementPortalException; +import org.gcube.vomanagement.usermanagement.exception.UserManagementSystemException; +import org.gcube.vomanagement.usermanagement.exception.UserRetrievalFault; +import org.gcube.vomanagement.usermanagement.impl.liferay.LiferayUserManager; import com.google.gwt.user.server.rpc.RemoteServiceServlet; import com.liferay.portal.kernel.exception.PortalException; @@ -64,10 +69,40 @@ public class SocialServiceImpl extends RemoteServiceServlet implements SocialSer else { System.out.println("Reading Profile"); _log.info(userid + " Reading Profile"); - return new UserContext(); + return getUserProfile(userid); } } + private UserContext getUserProfile(String username) { + ASLSession session = getASLSession(); + String email = username+"@isti.cnr.it"; + String fullName = username+" FULL"; + String thumbnailURL = "images/Avatar_default.png"; + if (withinPortal) { + try { + 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(); + HashMap vreNames = new HashMap(); + UserInfo userInfo = new UserInfo(username, fullName, thumbnailURL, user.getEmailAddress(), "", true, false, vreNames); + return new UserContext(userInfo, getHeadline(username), getInstitution(username), session.getScopeName(), true); + + } catch (Exception e) { + e.printStackTrace(); + return new UserContext(); + } + } 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(username, username+ "FULL", thumbnailURL, email, "fakeAccountUrl", true, false, fakeVreNames); + return new UserContext(user, null, "Institution", session.getScopeName(), true); + } + } + private UserContext getOwnProfile() { try { ASLSession session = getASLSession(); @@ -96,7 +131,7 @@ public class SocialServiceImpl extends RemoteServiceServlet implements SocialSer //fakeVreNames.put("/gcube/devNext/NexNext","NexNext"); UserInfo user = new UserInfo(getASLSession().getUsername(), fullName, thumbnailURL, email, "fakeAccountUrl", true, false, fakeVreNames); - return new UserContext(user, "headline", "Institution", session.getScopeName(), true); + return new UserContext(user, "", "", session.getScopeName(), true); } } catch (Exception e) { @@ -114,4 +149,47 @@ public class SocialServiceImpl extends RemoteServiceServlet implements SocialSer User user = OrganizationsUtil.validateUser(userid); return user.getComments(); } + + @Override + public Boolean saveHeadline(String newHeadline) { + com.liferay.portal.model.User user; + try { + user = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), getASLSession().getUsername()); + user.setJobTitle(escapeHtml(newHeadline)); + return (UserLocalServiceUtil.updateUser(user) != null); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + + } + @Override + public Boolean saveIsti(String institution) { + com.liferay.portal.model.User user; + try { + user = UserLocalServiceUtil.getUserByScreenName(OrganizationsUtil.getCompany().getCompanyId(), getASLSession().getUsername()); + user.setComments(escapeHtml(institution)); + return (UserLocalServiceUtil.updateUser(user) != null); + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + /** + * Escape an html string. Escaping data received from the client helps to + * prevent cross-site script vulnerabilities. + * + * @param html the html string to escape + * @return the escaped string + */ + private String escapeHtml(String html) { + if (html == null) { + return null; + } + return html.replaceAll("&", "&").replaceAll("<", "<") + .replaceAll(">", ">"); + } + + } 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 76292ac..d645b22 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 @@ -4,8 +4,6 @@ - - diff --git a/src/main/webapp/SocialProfile.css b/src/main/webapp/SocialProfile.css index cdc22aa..fee903a 100644 --- a/src/main/webapp/SocialProfile.css +++ b/src/main/webapp/SocialProfile.css @@ -23,14 +23,42 @@ font-weight: bold; } +.edit { + border: 1px solid #999 !important; + cursor: text !important; + opacity: 1.0 !important; +} + .headline { font-family: Helvetica, Arial, sans-serif; font-size: 16px; color: #444444; + border: 0; + cursor: default; + width: 250px; } .institution { font-family: Helvetica, Arial, sans-serif; - font-size: 12px; + font-size: 16px; color: #444444; + border: 0; + cursor: default; + width: 250px; +} + +.editImage { + background: url(images/edit.png) 0px 0px no-repeat; + height: 15px; + width: 15px; +} + +.editImage:hover { + background: url(images/edit.png) 0px -16px no-repeat; + cursor: pointer; + cursor: hand; +} + +.editImage:active { + background: url(images/edit.png) 0px -32px no-repeat; } \ No newline at end of file diff --git a/src/main/webapp/images/edit.png b/src/main/webapp/images/edit.png new file mode 100644 index 0000000..03d88a1 Binary files /dev/null and b/src/main/webapp/images/edit.png differ diff --git a/src/main/webapp/images/saving.gif b/src/main/webapp/images/saving.gif new file mode 100644 index 0000000..b644918 Binary files /dev/null and b/src/main/webapp/images/saving.gif differ