package org.gcube.portlets.user.shareupdates.client.form; import java.util.ArrayList; import net.eliasbalasis.tibcopagebus4gwt.client.PageBusAdapter; import net.eliasbalasis.tibcopagebus4gwt.client.PageBusAdapterException; import org.gcube.portal.databook.shared.ClientFeed; import org.gcube.portal.databook.shared.ClientFeed.ClientFeedJsonizer; import org.gcube.portal.databook.shared.FeedType; import org.gcube.portal.databook.shared.PrivacyLevel; import org.gcube.portal.databook.shared.UserInfo; import org.gcube.portlets.user.shareupdates.client.ShareUpdateService; import org.gcube.portlets.user.shareupdates.client.ShareUpdateServiceAsync; import org.gcube.portlets.user.shareupdates.shared.LinkPreview; import org.gcube.portlets.user.shareupdates.shared.UserSettings; import org.gcube.portlets.widgets.fileupload.client.events.FileUploadCompleteEvent; import org.gcube.portlets.widgets.fileupload.client.events.FileUploadCompleteEventHandler; import org.gcube.portlets.widgets.fileupload.client.view.FileSubmit; import org.gcube.portlets.widgets.fileupload.client.view.UploadProgressDialog; import org.gcube.portlets.widgets.fileupload.client.view.UploadProgressPanel; import org.gcube.portlets.widgets.fileupload.client.view.UploadProgressView; import org.jsonmaker.gwt.client.Jsonizer; import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.event.dom.client.ClickEvent; import com.google.gwt.event.shared.HandlerManager; import com.google.gwt.uibinder.client.UiBinder; import com.google.gwt.uibinder.client.UiFactory; import com.google.gwt.uibinder.client.UiField; import com.google.gwt.uibinder.client.UiHandler; import com.google.gwt.user.client.Timer; 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.HTMLPanel; import com.google.gwt.user.client.ui.Image; import com.google.gwt.user.client.ui.ListBox; import com.google.gwt.user.client.ui.Widget; /** * * @author Massimiliano Assante * @version 1.2 Nov 2012 * */ public class ShareUpdateForm extends Composite { /** * Create a remote service proxy to talk to the server-side Greeting service. */ private final ShareUpdateServiceAsync shareupdateService = GWT .create(ShareUpdateService.class); final PageBusAdapter pageBusAdapter = new PageBusAdapter(); protected final static String SHARE_UPDATE_TEXT = "Share an update or paste a link, use “@” to mention someone"; protected final static String ERROR_UPDATE_TEXT = "Looks like empty to me!"; private final static String LISTBOX_LEVEL = " - "; public static final String loading = GWT.getModuleBaseURL() + "../images/avatarLoader.gif"; public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png"; private HandlerManager eventBus = new HandlerManager(null); private static ShareUpdateFormUiBinder uiBinder = GWT .create(ShareUpdateFormUiBinder.class); private LinkPreviewer myLinkPreviewer; private UploadProgressPanel uploadProgress; interface ShareUpdateFormUiBinder extends UiBinder { } private static ShareUpdateForm singleton; public static ShareUpdateForm get() { return singleton; } @UiField HTMLPanel mainPanel; @UiField LinkPlaceholder preview; @UiField Button submitButton; @UiField Button attachButton; @UiField Image avatarImage; @UiField SuperPosedTextArea shareTextArea; @UiField ListBox privacyLevel = new ListBox(false); UserInfo myUserInfo; public ShareUpdateForm() { initWidget(uiBinder.createAndBindUi(this)); singleton = this; bind(); avatarImage.setUrl(loading); shareTextArea.setText(SHARE_UPDATE_TEXT); shareupdateService.getUserSettings(new AsyncCallback() { public void onFailure(Throwable caught) { avatarImage.setSize("60px", "60px"); avatarImage.setUrl(avatar_default); } public void onSuccess(UserSettings userSettings) { myUserInfo = userSettings.getUserInfo(); avatarImage.getElement().getParentElement().setAttribute("href", myUserInfo.getAccountURL()); avatarImage.setSize("60px", "60px"); avatarImage.setUrl(myUserInfo.getAvatarId()); String singleVREName = ""; if (myUserInfo.getOwnVREs().size() > 1) { privacyLevel.addItem("My VREs", PrivacyLevel.VRES.toString()); for (String vreId : myUserInfo.getOwnVREs().keySet()) privacyLevel.addItem(LISTBOX_LEVEL + myUserInfo.getOwnVREs().get(vreId), vreId); } else if (myUserInfo.getOwnVREs().size() == 1) for (String vreId : myUserInfo.getOwnVREs().keySet()) { singleVREName = myUserInfo.getOwnVREs().get(vreId); privacyLevel.addItem(LISTBOX_LEVEL + singleVREName, vreId); } //privacyLevel.addItem("My Connections", PrivacyLevel.CONNECTION.toString()); if (myUserInfo.isAdmin() && userSettings.isInfrastructure()) privacyLevel.addItem("Anyone", PrivacyLevel.PORTAL.toString()); //change css if deployed in VRE scope if (!userSettings.isInfrastructure()) { mainPanel.addStyleName("framed"); Document.get().getElementById("staticPrivacyLevel").setInnerText(singleVREName); } else privacyLevel.setVisible(true); } }); } /** Used by UiBinder to instantiate UploadProgressView */ @UiFactory UploadProgressPanel instatiateProgressView() { uploadProgress = new UploadProgressPanel(eventBus); uploadProgress.setVisible(false); return uploadProgress; } private void bind() { /** * get the uploaded file result */ eventBus.addHandler(FileUploadCompleteEvent.TYPE, new FileUploadCompleteEventHandler() { @Override public void onUploadComplete(FileUploadCompleteEvent event) { String absolutePathOnServer = event.getUploadedFileInfo().getAbsolutePath(); GWT.log("uploaded on Server here: " + absolutePathOnServer); checkFile(event.getUploadedFileInfo().getFilename(), absolutePathOnServer); } }); } @UiHandler("shareTextArea") void onShareUpdateClick(ClickEvent e) { shareTextArea.removeSampleText(); } @UiHandler("attachButton") void onAttachClick(ClickEvent e) { GWT.log("aaa"); if (myLinkPreviewer == null) { uploadProgress.initialize(); uploadProgress.setVisible(true); attachButton.setVisible(false); } else { Window.alert("You cannot post two files, please remove the previous one first."); } } @UiHandler("submitButton") void onClick(ClickEvent e) { shareupdateService.getUserSettings(new AsyncCallback() { public void onFailure(Throwable caught) { Window.alert("Ops! we encountered some problems delivering your message, server is not responding, please try again in a short while."); } public void onSuccess(UserSettings result) { if (result.getUserInfo().getUsername().equals("test.user")) { Window.alert("Your session has expired, please log out and login again"); return; } myUserInfo = result.getUserInfo(); String toShare = shareTextArea.getText().trim(); if (toShare.equals(SHARE_UPDATE_TEXT) || toShare.equals(ERROR_UPDATE_TEXT) || toShare.equals("")) { shareTextArea.addStyleName("error"); shareTextArea.setText(ERROR_UPDATE_TEXT); return; } //then you can post, but pass html String toPost = shareTextArea.getText(); postTweet(toPost, shareTextArea.getMentionedUsers()); } }); } /** * * @param textToPost */ private void postTweet(String textToPost, ArrayList mentionedUsers) { String toShare = escapeHtml(textToPost); if (! checkTextLength(toShare)) { Window.alert("We found a single word containing more than 50 chars and it's not a link, is it meaningful?"); return; } submitButton.setEnabled(false); shareTextArea.setEnabled(false); String vreId = ""; if (getPrivacyLevel() == PrivacyLevel.SINGLE_VRE) { vreId = privacyLevel.getValue(privacyLevel.getSelectedIndex()); } String linkTitle = ""; String linkDescription = ""; String linkUrl = ""; String linkUrlThumbnail = ""; String linkHost = ""; if (myLinkPreviewer != null) { linkTitle = myLinkPreviewer.getLinkTitle(); linkDescription = myLinkPreviewer.getLinkDescription(); linkUrl = myLinkPreviewer.getUrl(); linkUrlThumbnail = myLinkPreviewer.getUrlThumbnail(); linkHost = myLinkPreviewer.getHost(); } shareupdateService.share(toShare, FeedType.TWEET, getPrivacyLevel(), vreId, linkTitle, linkDescription, linkUrl, linkUrlThumbnail, linkHost, mentionedUsers, new AsyncCallback() { public void onFailure(Throwable caught) { submitButton.setEnabled(true); shareTextArea.setEnabled(true); shareTextArea.setText(SHARE_UPDATE_TEXT); shareTextArea.cleanHighlihterDiv(); preview.clear(); myLinkPreviewer = null; } public void onSuccess(ClientFeed feed) { submitButton.setEnabled(true); shareTextArea.setEnabled(true); shareTextArea.setText(SHARE_UPDATE_TEXT); shareTextArea.cleanHighlihterDiv(); preview.clear(); myLinkPreviewer = null; if (feed == null) Window.alert("Ops! we encountered some problems delivering your message, please try again in a short while."); else { // publish a message with the refresh notification try { pageBusAdapter.PageBusPublish("org.gcube.portal.databook.shared", feed, (Jsonizer)GWT.create(ClientFeedJsonizer.class)); } catch (PageBusAdapterException ex) { GWT.log(ex.getMessage()); } } } }); } private PrivacyLevel getPrivacyLevel() { String selected = privacyLevel.getValue(privacyLevel.getSelectedIndex()); if (selected.compareTo(PrivacyLevel.CONNECTION.toString()) == 0) return PrivacyLevel.CONNECTION; else if (selected.compareTo(PrivacyLevel.VRES.toString()) == 0) return PrivacyLevel.VRES; else if (selected.compareTo(PrivacyLevel.PRIVATE.toString()) == 0) return PrivacyLevel.PRIVATE; else if (selected.compareTo(PrivacyLevel.PORTAL.toString()) == 0) return PrivacyLevel.PORTAL; else return PrivacyLevel.SINGLE_VRE; } /** * 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(">", ">"); } /** * called when pasting a possible link * @param linkToCheck */ protected void checkLink(String textToCheck) { if (myLinkPreviewer == null) { String [] parts = textToCheck.split("\\s"); // Attempt to convert each item into an URL. for( String item : parts ) { if (item.startsWith("http")) { preview.add(new LinkLoader()); //GWT.log("It's http link:" + linkToCheck); shareupdateService.checkLink(textToCheck, new AsyncCallback() { public void onFailure(Throwable caught) { preview.clear(); } public void onSuccess(LinkPreview result) { preview.clear(); if (result != null) addPreview(result); } }); break; } } } else { Window.alert("You cannot post two links, please remove the previous one first."); } } /** * called when the file was correctly uploaded on server * @param fileName the name of the file * @param absolutePathOnServer the path of the file ending with its name on the server temp */ protected void checkFile(String fileName, String absolutePathOnServer) { preview.add(new LinkLoader()); shareupdateService.checkUploadedFile(fileName, absolutePathOnServer, new AsyncCallback() { public void onFailure(Throwable caught) { uploadProgress.showRegisteringResult(false); preview.clear(); attachButton.setVisible(true); } public void onSuccess(LinkPreview result) { preview.clear(); uploadProgress.setVisible(false); if (result != null) addPreview(result); } }); } /** * called when pasting. it tries to avoid pasting long non spaced strings * @param linkToCheck */ private boolean checkTextLength(String textToCheck) { String [] parts = textToCheck.split("\\s"); // check the length of tokens for( String item : parts ) { if (! item.startsWith("http")) { //url are accepted as they can be trunked if (item.length() > 50) { return false; } } } return true; } /** * add the link preview in the view * @param result */ private void addPreview(LinkPreview result) { uploadProgress.setVisible(false); myLinkPreviewer = new LinkPreviewer(this, result); preview.add(myLinkPreviewer); } /** * */ protected void cancelPreview() { preview.clear(); myLinkPreviewer = null; attachButton.setVisible(true); } }