diff --git a/.gwt/.gwt-log b/.gwt/.gwt-log
new file mode 100644
index 0000000..e69de29
diff --git a/.settings/com.google.gdt.eclipse.core.prefs b/.settings/com.google.gdt.eclipse.core.prefs
index e783f74..d1c6808 100644
--- a/.settings/com.google.gdt.eclipse.core.prefs
+++ b/.settings/com.google.gdt.eclipse.core.prefs
@@ -1,5 +1,5 @@
eclipse.preferences.version=1
jarsExcludedFromWebInfLib=
-lastWarOutDir=/Users/massi/Documents/workspace/share-updates/target/share-updates-1.6.1-SNAPSHOT
+lastWarOutDir=/home/costantino/workspace/share-updates/target/share-updates-1.8.2-SNAPSHOT
warSrcDir=src/main/webapp
warSrcDirIsOutput=false
diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component
index 27d5949..8ed83f9 100644
--- a/.settings/org.eclipse.wst.common.component
+++ b/.settings/org.eclipse.wst.common.component
@@ -4,10 +4,7 @@
-
- uses
-
-
+
uses
diff --git a/pom.xml b/pom.xml
index 5e9be88..6d475c5 100644
--- a/pom.xml
+++ b/pom.xml
@@ -48,6 +48,11 @@
+
+ xerces
+ xercesImpl
+ 2.9.1
+
com.google.gwt
gwt-user
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/ShareUpdates.java b/src/main/java/org/gcube/portlets/user/shareupdates/client/ShareUpdates.java
index fd5e60a..2880702 100644
--- a/src/main/java/org/gcube/portlets/user/shareupdates/client/ShareUpdates.java
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/ShareUpdates.java
@@ -4,16 +4,33 @@ import org.gcube.portlets.user.gcubewidgets.client.ClientScopeHelper;
import org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm;
import com.google.gwt.core.client.EntryPoint;
+import com.google.gwt.core.client.ScriptInjector;
+import com.google.gwt.core.shared.GWT;
import com.google.gwt.user.client.Window.Location;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.RootPanel;
/**
* Entry point classes define onModuleLoad()
.
+ * @author Massimiliano Assante at ISTI CNR
+ * @author Costantino Perciante at ISTI CNR
*/
public class ShareUpdates implements EntryPoint {
public void onModuleLoad() {
+
+ // check if jQuery is available
+ boolean jQueryLoaded = isjQueryLoaded();
+
+ if(jQueryLoaded)
+ GWT.log("Injecting : http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js");
+ else{
+ ScriptInjector.fromUrl("http://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js")
+ .setWindow(ScriptInjector.TOP_WINDOW)
+ .inject();
+ }
+
+ // start UI and related stuff
ClientScopeHelper.getService().setScope(Location.getHref(), new AsyncCallback() {
@Override
public void onSuccess(Boolean result) {
@@ -24,4 +41,15 @@ public class ShareUpdates implements EntryPoint {
}
});
}
+
+ /**
+ * Checks if jQuery is loaded.
+ *
+ * @return true, if jQuery is loaded, false otherwise
+ */
+ private native boolean isjQueryLoaded() /*-{
+
+ return (typeof $wnd['jQuery'] !== 'undefined');
+
+ }-*/;
}
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachedFile.java b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachedFile.java
new file mode 100644
index 0000000..b2648bb
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachedFile.java
@@ -0,0 +1,50 @@
+package org.gcube.portlets.user.shareupdates.client.view;
+
+public class AttachedFile {
+
+ private String fileName;
+ private String fileAbsolutePathOnServer;
+ private AttachmentPreviewer atPrev;
+ private boolean correctlyUploaded;
+
+ /**
+ *
+ * @param fileName name of the file
+ * @param fileAbsolutePathOnServer path on the server
+ * @param atPrev object that shows such attachment
+ * @param uploaded has been it correctly uploaded on the server?
+ */
+ public AttachedFile(String fileName, String fileAbsolutePathOnServer,
+ AttachmentPreviewer atPrev, boolean uploaded) {
+ super();
+ this.fileName = fileName;
+ this.fileAbsolutePathOnServer = fileAbsolutePathOnServer;
+ this.atPrev = atPrev;
+ this.correctlyUploaded = uploaded;
+ }
+ public String getFileName() {
+ return fileName;
+ }
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+ public String getFileAbsolutePathOnServer() {
+ return fileAbsolutePathOnServer;
+ }
+ public void setFileAbsolutePathOnServer(String fileAbsolutePathOnServer) {
+ this.fileAbsolutePathOnServer = fileAbsolutePathOnServer;
+ }
+ public AttachmentPreviewer getAtPrev() {
+ return atPrev;
+ }
+ public void setAtPrev(AttachmentPreviewer atPrev) {
+ this.atPrev = atPrev;
+ }
+ public boolean isCorrectlyUploaded() {
+ return correctlyUploaded;
+ }
+ public void setCorrectlyUploaded(boolean correctlyUploaded) {
+ this.correctlyUploaded = correctlyUploaded;
+ }
+
+}
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachmentPreviewer.java b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachmentPreviewer.java
new file mode 100644
index 0000000..b57e2bd
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachmentPreviewer.java
@@ -0,0 +1,126 @@
+package org.gcube.portlets.user.shareupdates.client.view;
+
+import com.google.gwt.core.client.GWT;
+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.uibinder.client.UiHandler;
+import com.google.gwt.user.client.Window;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.Widget;
+
+public class AttachmentPreviewer extends Composite {
+
+ private static AttachmentPreviewerUiBinder uiBinder = GWT
+ .create(AttachmentPreviewerUiBinder.class);
+
+ interface AttachmentPreviewerUiBinder extends
+ UiBinder {
+ }
+
+ public AttachmentPreviewer() {
+ initWidget(uiBinder.createAndBindUi(this));
+ }
+
+ private static final String DELETE_ATTACHMENT = "The attachment won't be saved. Would you like to continue?";
+
+ @UiField
+ HTML deleteAttachment;
+
+ @UiField
+ Image imagePreview;
+
+ @UiField
+ Label fileName;
+
+ @UiField
+ Label resultLabel;
+
+ @UiField
+ Image resultImage;
+
+ // Parent of this AttachmentPreviewer object
+ private Placeholder parent;
+
+ // the ShareUpdateForm
+ private ShareUpdateForm shareUpdateForm;
+
+ public AttachmentPreviewer(String fileName, String urlImagePreview, Placeholder parent, ShareUpdateForm shareUpdateForm) {
+
+ initWidget(uiBinder.createAndBindUi(this));
+
+ // set filename and temp attachment url
+ this.fileName.setText(fileName);
+ this.imagePreview.setUrl(urlImagePreview);
+
+ // style the delete button
+ this.deleteAttachment.setStyleName("su-deleteAttachment");
+ this.deleteAttachment.setTitle("Cancel");
+
+ // save parent
+ this.parent = parent;
+
+ // save the shareUpdateForm object, since it maintains the list of attached files
+ this.shareUpdateForm = shareUpdateForm;
+ }
+
+ @UiHandler("deleteAttachment")
+ void onClick(ClickEvent e) {
+
+ // alert the user
+ boolean confirm = Window.confirm(DELETE_ATTACHMENT);
+
+ if(!confirm)
+ return;
+
+ // we have to remove the AttachmentPreview object (that is, this object) and
+ // remove the file from the List of AttachedFiles
+ parent.remove(this);
+ shareUpdateForm.removeAttachedFile(this);
+
+ }
+
+ /**
+ * set the label and the that shows if the file has been saved or not
+ * @param result
+ * @param urlImageResult
+ */
+ public void setResultAttachment(String result, String urlImageResult){
+ this.resultLabel.setText(result);
+ this.resultImage.setUrl(urlImageResult);
+ }
+
+ /**
+ * Change the image preview of the attachment from the default one
+ * @param urlImagePreview
+ */
+ public void setImagePreview(String urlImagePreview){
+ this.imagePreview.setUrl(urlImagePreview);
+ }
+
+ /**
+ * Change style of part of this object to allow the user to retry to upload the file
+ * @param tooltip
+ * @param retryToAttachImageUrl
+ */
+ public void setImagePreviewToRetry(String tooltip, String retryToAttachImageUrl) {
+
+ this.imagePreview.setUrl(retryToAttachImageUrl);
+ this.imagePreview.setTitle(tooltip);
+
+ // add the handler on the icon
+ this.imagePreview.addClickHandler(new ClickHandler() {
+
+ @Override
+ public void onClick(ClickEvent event) {
+ Window.alert("Retry to attach handler to be implemented...");
+ }
+ });
+
+ }
+
+}
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachmentPreviewer.ui.xml b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachmentPreviewer.ui.xml
new file mode 100644
index 0000000..f1c8cc3
--- /dev/null
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/AttachmentPreviewer.ui.xml
@@ -0,0 +1,48 @@
+
+
+
+ .image-preview {
+ align: left;
+ margin-right: 5px;
+ margin-left: 2px;
+ display: inline;
+ margin-top: 5px;
+ height: 40px;
+ }
+
+ .attach-result {
+ vertical-align: top;
+ display: inline-block;
+ font-size: 10px;
+ font-weight: bold;
+ }
+
+ .image-result {
+ margin-left: 4px;
+ width: 10px;
+ vertical-align: middle;
+ }
+
+ .container-style {
+ border-style: solid;
+ background-color: #DCDCDC;
+ border-width: thin;
+ margin-left: 30px;
+ margin-top: 1px;
+ width: 565px;
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/LinkPreviewer.java b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/LinkPreviewer.java
index 40a7b08..af24f63 100644
--- a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/LinkPreviewer.java
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/LinkPreviewer.java
@@ -26,8 +26,6 @@ public class LinkPreviewer extends Composite {
private LinkPreview toShow;
- private SaveInWorkspaceBox saveCopy;
-
private boolean showImage = true;
@UiField
@@ -44,10 +42,8 @@ public class LinkPreviewer extends Composite {
CheckBox hideCheckBox;
@UiField
CheckBox hideImageCheckBox;
- @UiField
- Placeholder uploadInWS;
- public LinkPreviewer(ShareUpdateForm parent, LinkPreview toShow, boolean isFilePreview) {
+ public LinkPreviewer(ShareUpdateForm parent, LinkPreview toShow) {
initWidget(uiBinder.createAndBindUi(this));
closeImage.setStyleName("su-closeImage");
closeImage.setTitle("Cancel");
@@ -67,10 +63,6 @@ public class LinkPreviewer extends Composite {
urlText.setHTML((url.length() > 80) ? url.substring(0, 80)+"..." : url);
switcher.setImages(toShow.getImageUrls());
- if (isFilePreview) {
- saveCopy = new SaveInWorkspaceBox();
- uploadInWS.add(saveCopy);
- }
}
public ImageSwitcher getSwitcher() {
@@ -79,7 +71,7 @@ public class LinkPreviewer extends Composite {
@UiHandler("closeImage")
void onDeleteFeedClick(ClickEvent e) {
- parent.cancelPreview();
+ parent.cancelLinkPreview();
}
@UiHandler("hideImageCheckBox")
@@ -109,10 +101,4 @@ public class LinkPreviewer extends Composite {
return null;
return switcher.getSelectedImageURL();
}
- protected boolean isSharingFile() {
- return (saveCopy != null);
- }
- protected boolean isSaveCopySelected() {
- return isSharingFile() ? saveCopy.getValue() : false;
- }
}
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/Placeholder.java b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/Placeholder.java
index 0e3a2c3..69a6da9 100644
--- a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/Placeholder.java
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/Placeholder.java
@@ -1,11 +1,13 @@
package org.gcube.portlets.user.shareupdates.client.view;
-import com.google.gwt.user.client.ui.SimplePanel;
+
+import com.google.gwt.user.client.ui.VerticalPanel;
/**
- *
- * @author massi
+ * This panel will contain the attachments/previews
+ * @author Massimiliano Assante at ISTI CNR
+ * @author Costantino Perciante at ISTI CNR
*
*/
-public class Placeholder extends SimplePanel {
+public class Placeholder extends VerticalPanel {
}
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/ShareUpdateForm.java b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/ShareUpdateForm.java
index f826a4a..641a0ba 100644
--- a/src/main/java/org/gcube/portlets/user/shareupdates/client/view/ShareUpdateForm.java
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/client/view/ShareUpdateForm.java
@@ -1,6 +1,8 @@
package org.gcube.portlets.user.shareupdates.client.view;
import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
import net.eliasbalasis.tibcopagebus4gwt.client.PageBusAdapter;
import net.eliasbalasis.tibcopagebus4gwt.client.PageBusAdapterException;
@@ -16,17 +18,24 @@ 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.UploadProgressPanel;
import org.jsonmaker.gwt.client.Jsonizer;
+import com.github.gwtbootstrap.client.ui.Button;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
+import com.google.gwt.dom.client.Style.BorderStyle;
import com.google.gwt.dom.client.Style.Display;
+import com.google.gwt.dom.client.Style.FontWeight;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.ClickEvent;
-import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.event.dom.client.DragLeaveEvent;
+import com.google.gwt.event.dom.client.DragLeaveHandler;
+import com.google.gwt.event.dom.client.DragOverEvent;
+import com.google.gwt.event.dom.client.DragOverHandler;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
@@ -34,67 +43,84 @@ import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
-import com.github.gwtbootstrap.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FileUpload;
-import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HTMLPanel;
-import com.google.gwt.user.client.ui.HasAlignment;
-import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.ValueBoxBase.TextAlignment;
import com.google.gwt.user.client.ui.Widget;
/**
*
- * @author Massimiliano Assante
+ * @author Massimiliano Assante at ISTI CNR
+ * @author Costantino Perciante at ISTI CNR
*
*/
public class ShareUpdateForm extends Composite {
- /**
- * Create a remote service proxy to talk to the server-side Greeting service.
- */
+
+ //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();
+
// the label for all Vres/channels
private final static String ALL_VRES = "Share with: your Virtual Research Environments";
+ // Labels
protected final static String SHARE_UPDATE_TEXT = "Share an update or a link, use “@” to mention and “#” to add a topic";
protected final static String ERROR_UPDATE_TEXT = "Looks like empty to me!";
public final static String NO_TEXT_FILE_SHARE = "_N0_73X7_SH4R3_";
private final static String LISTBOX_LEVEL = " - ";
+ public static final String DROP_FILE_HERE_TEXT = "Drop your file(s) here!";
+ public static final String ATTACHMENT_LOADED = "Attachment loaded!";
+ public static final String ATTACHMENT_NOT_LOADED = "Attachment not loaded!";
+ private static final String RETRY_TO_ATTACH_MESSAGE = "Retry to attach this file";
+ private static final String DELETE_LINK_PREVIEW = "The link preview will be removed. Would you like to continue?";
+ private static final String DELETE_ATTACHMENTS = "The attachment(s) will be removed. Would you like to continue?";
-
+ // image urls
public static final String loading = GWT.getModuleBaseURL() + "../images/avatarLoader.gif";
public static final String avatar_default = GWT.getModuleBaseURL() + "../images/Avatar_default.png";
public static final String attach = GWT.getModuleBaseURL() + "../images/attach.png";
+ public static final String attachedDefault = GWT.getModuleBaseURL() + "../images/attachment_default.png";
+ public static final String loadedAttachment = GWT.getModuleBaseURL() + "../images/load.png";
+ public static final String notLoadedAttachment = GWT.getModuleBaseURL() + "../images/not_load.png";
+ public static final String retryToAttach = GWT.getModuleBaseURL() + "../images/reload.png";
- /**
- * needed to know where to find the (possible) uploaded file
- */
- private String uploadedFilePathOnServer;
- private String uploadedFileNameOnServer;
+ // maximum number of files that can be attached!
+ private static final int MAX_NUMBER_ATTACHMENTS = 10;
+
+ // remember the previous text in the textarea (while handling drag and drop)
+ private static String previousText;
+
+ // list of attachedFiles (both correctly or not correctly uploaded)
+ private List listOfAttachedFiles = new ArrayList<>();
private HandlerManager eventBus = new HandlerManager(null);
private static ShareUpdateFormUiBinder uiBinder = GWT
.create(ShareUpdateFormUiBinder.class);
+ // The link previewer
private LinkPreviewer myLinkPreviewer;
+ // panel that show the in progress upload of an attachment
private UploadProgressPanel uploadProgress;
interface ShareUpdateFormUiBinder extends UiBinder {
}
+ // this instance
private static ShareUpdateForm singleton;
public static ShareUpdateForm get() {
return singleton;
}
+
@UiField
HTMLPanel mainPanel;
+
@UiField
Placeholder preview;
@@ -107,7 +133,8 @@ public class ShareUpdateForm extends Composite {
@UiField
Image avatarImage;
- @UiField SuperPosedTextArea shareTextArea;
+ @UiField
+ SuperPosedTextArea shareTextArea;
@UiField
ListBox privacyLevel = new ListBox();
@@ -115,23 +142,12 @@ public class ShareUpdateForm extends Composite {
@UiField
ListBox notifyListbox = new ListBox();
+ // requested user's information
private UserInfo myUserInfo;
-
- 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);
- }
- });
- }
-
+ /**
+ * Constructor
+ */
public ShareUpdateForm() {
initWidget(uiBinder.createAndBindUi(this));
singleton = this;
@@ -140,9 +156,8 @@ public class ShareUpdateForm extends Composite {
shareTextArea.setText(SHARE_UPDATE_TEXT);
attachButton.getElement().getStyle().setDisplay(Display.INLINE);
- // attachButton.setHTML(" ");
attachButton.addStyleName("upload-btn-m");
-
+
shareupdateService.getUserSettings(new AsyncCallback() {
public void onFailure(Throwable caught) {
avatarImage.setUrl(avatar_default);
@@ -167,9 +182,9 @@ public class ShareUpdateForm extends Composite {
privacyLevel.addItem(LISTBOX_LEVEL + "Share with: " + singleVREName, vreId);
}
- //privacyLevel.addItem("My Connections", PrivacyLevel.CONNECTION.toString());
if (myUserInfo.isAdmin())
privacyLevel.addItem("Share with: Everyone", PrivacyLevel.PORTAL.toString());
+
//change css if deployed in VRE scope
if (!userSettings.isInfrastructure()) {
mainPanel.addStyleName("framed");
@@ -184,6 +199,84 @@ public class ShareUpdateForm extends Composite {
privacyLevel.setVisible(true);
attachButton.setVisible(true);
submitButton.setVisible(true);
+
+ // check if DND can be activated and enable it if it's possible
+ if(checkDNDAvailability()){
+
+ // add drag over handler on shareTextArea
+ shareTextArea.addDragOverHandler(new DragOverHandler() {
+
+ @Override
+ public void onDragOver(DragOverEvent event) {
+
+ GWT.log("Drag over handler");
+
+ // save current text (note that the DragOverEvent event can be fired several times)
+ boolean conditionToSave = !shareTextArea.getText().equals(DROP_FILE_HERE_TEXT) && !shareTextArea.getText().equals(SHARE_UPDATE_TEXT);
+ previousText = conditionToSave ? shareTextArea.getText() : previousText;
+
+ // change border properties
+ shareTextArea.getElement().getStyle().setBorderStyle(BorderStyle.DASHED);
+ shareTextArea.getElement().getStyle().setBorderColor("rgba(82, 168, 236, 0.6)");
+ shareTextArea.getElement().getStyle().setBorderWidth(2.5, Unit.PX);
+
+ // change background color
+ shareTextArea.getElement().getStyle().setBackgroundColor("rgba(82, 168, 236, 0.2)");
+
+ // enlarge the window
+ Document.get().getElementById("highlighterContainer").getStyle().setHeight(52, Unit.PX);
+ Document.get().getElementById("highlighter").getStyle().setHeight(52, Unit.PX);
+ Document.get().getElementById("postTextArea").getStyle().setHeight(52, Unit.PX);
+
+ // add "Drop file here" text
+ shareTextArea.setText(DROP_FILE_HERE_TEXT);
+ shareTextArea.setAlignment(TextAlignment.CENTER);
+ shareTextArea.getElement().getStyle().setFontWeight(FontWeight.BOLD);
+ shareTextArea.getElement().getStyle().setPaddingTop(
+ (Double.parseDouble(shareTextArea.getElement().getStyle().getHeight().replace("px", "")) + 20)/2.0, Unit.PX);
+
+ // set the color of the text if needed to gray
+ if(!previousText.equals(SHARE_UPDATE_TEXT))
+ shareTextArea.getElement().getStyle().setColor("#999");
+
+ }
+ });
+
+ // clear drag over effect
+ shareTextArea.addDragLeaveHandler(new DragLeaveHandler() {
+
+ @Override
+ public void onDragLeave(DragLeaveEvent event) {
+
+ GWT.log("Drag leave handler");
+
+ // remove style changes
+ resetTextArea();
+
+ }
+
+ });
+
+ // enable shareTextArea as drop target (using native javascript)
+ addNativeDropHandler(singleton, FileSubmit.URL);
+
+ }
+ }
+ });
+ }
+
+ /**
+ * Bind events to manage
+ */
+ 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);
}
});
}
@@ -208,15 +301,28 @@ public class ShareUpdateForm extends Composite {
@UiHandler("attachButton")
void onAttachClick(ClickEvent e) {
- if (myLinkPreviewer == null) {
- FileUpload up = uploadProgress.initialize();
- up.setVisible(false);
- fileBrowse(up.getElement());
- uploadProgress.setVisible(true);
- } else {
- Window.alert("You cannot post two files, please remove the previous one first.");
+
+ // check if there is a linkpreview
+ if(myLinkPreviewer != null){
+
+ // in this case let the user choose what to do
+ boolean confirm = Window.confirm(DELETE_LINK_PREVIEW);
+
+ if(!confirm)
+ return;
+
+ // remove preview
+ cancelLinkPreview();
}
+
+ // proceed with the upload
+ FileUpload up = uploadProgress.initialize();
+ up.setVisible(false);
+ fileBrowse(up.getElement());
+ uploadProgress.setVisible(true);
+
}
+
/**
* this simulates the click on the hidden native GWT FileUpload Button
* @param el
@@ -228,7 +334,10 @@ public class ShareUpdateForm extends Composite {
@UiHandler("submitButton")
void onClick(ClickEvent e) {
- attachButton.getElement().getStyle().setVisibility(Visibility.VISIBLE); //beacuse otherwise it looses the other properties setting
+
+ //because otherwise it looses the other properties setting
+ attachButton.getElement().getStyle().setVisibility(Visibility.VISIBLE);
+
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.");
@@ -242,7 +351,7 @@ public class ShareUpdateForm extends Composite {
String toShare = shareTextArea.getText().trim();
//We allow to post a file without writing nothing in the sharing textarea
- if (myLinkPreviewer != null && myLinkPreviewer.isSharingFile() && (toShare.equals(SHARE_UPDATE_TEXT) || toShare.equals(ERROR_UPDATE_TEXT) || toShare.equals("")) ) {
+ if (myLinkPreviewer != null && (toShare.equals(SHARE_UPDATE_TEXT) || toShare.equals(ERROR_UPDATE_TEXT) || toShare.equals("")) ) {
toShare = NO_TEXT_FILE_SHARE;
}
if (toShare.equals(SHARE_UPDATE_TEXT) || toShare.equals(ERROR_UPDATE_TEXT) || toShare.equals("")) {
@@ -284,10 +393,11 @@ public class ShareUpdateForm extends Composite {
linkUrl = myLinkPreviewer.getUrl();
linkUrlThumbnail = myLinkPreviewer.getUrlThumbnail();
linkHost = myLinkPreviewer.getHost();
- if (myLinkPreviewer.isSaveCopySelected()) {
- fileName = uploadedFileNameOnServer;
- filePath = uploadedFilePathOnServer;
- }
+ // TODO handle attachments
+ // if (myLinkPreviewer.isSaveCopySelected()) {
+ // fileName = uploadedFileNameOnServer;
+ // filePath = uploadedFilePathOnServer;
+ // }
}
LinkPreview preview2Share = new LinkPreview(linkTitle, linkDescription, linkUrl, linkHost, null);
boolean notifyGroup = notifyListbox.getSelectedIndex() > 0;
@@ -362,6 +472,22 @@ public class ShareUpdateForm extends Composite {
// Attempt to convert each item into an URL.
for( String item : parts ) {
if (item.startsWith("http") || item.startsWith("www")) {
+
+ // check if there are attachments and inform the user that they will be lost
+ if(!listOfAttachedFiles.isEmpty()){
+
+ // in this case let the user to choose what to do
+ boolean confirm = Window.confirm(DELETE_ATTACHMENTS);
+
+ if(!confirm)
+ return;
+
+ // else... remove attachments and continue
+ listOfAttachedFiles.clear();
+ preview.clear();
+
+ }
+
preview.add(new LinkLoader());
submitButton.setEnabled(false);
//GWT.log("It's http link:" + linkToCheck);
@@ -374,7 +500,7 @@ public class ShareUpdateForm extends Composite {
public void onSuccess(LinkPreview result) {
preview.clear();
if (result != null)
- addPreview(result, false);
+ addPreviewLink(result);
submitButton.setEnabled(true);
}
});
@@ -393,14 +519,26 @@ public class ShareUpdateForm extends Composite {
* @param absolutePathOnServer the path of the file ending with its name on the server temp
*/
protected void checkFile(final String fileName, final String absolutePathOnServer) {
- preview.add(new LinkLoader());
+
+ // create temp view of the attached file and add to the previewer
+ final AttachmentPreviewer atPrev = new AttachmentPreviewer(fileName, attachedDefault, preview, this);
+ preview.add(atPrev);
+
+ // disable the submit button till we know the result of the upload process
submitButton.setEnabled(false);
+
shareupdateService.checkUploadedFile(fileName, absolutePathOnServer, new AsyncCallback() {
public void onFailure(Throwable caught) {
- GWT.log("Failed");
+ GWT.log("Upload of the file failed!");
uploadProgress.showRegisteringResult(false);
- preview.clear();
+ uploadProgress.setVisible(false);
+
+ addPreviewAttachment(null, atPrev);
+ listOfAttachedFiles.add(new AttachedFile(fileName, absolutePathOnServer, atPrev, false));
submitButton.setEnabled(true);
+
+ /*preview.clear();
+
final HorizontalPanel hp = new HorizontalPanel();
final Button close = new Button("Try Again");
final HTML reportIssue = new HTML(""
@@ -417,24 +555,23 @@ public class ShareUpdateForm extends Composite {
hp.setVerticalAlignment(HasAlignment.ALIGN_MIDDLE);
hp.add(close);
hp.add(reportIssue);
- preview.add(hp);
+ preview.add(hp);*/
}
- public void onSuccess(LinkPreview result) {
- preview.clear();
+ public void onSuccess(LinkPreview result) {
+
+ if(result == null)
+ return;
+
uploadProgress.setVisible(false);
- if (result != null)
- addPreview(result, true);
- attachButton.getElement().getStyle().setVisibility(Visibility.HIDDEN); //beacuse otherwise it looses the other properties setting
- uploadedFilePathOnServer = absolutePathOnServer;
- uploadedFileNameOnServer = fileName;
+ addPreviewAttachment(result, atPrev);
+ listOfAttachedFiles.add(new AttachedFile(fileName, absolutePathOnServer, atPrev, true));
submitButton.setEnabled(true);
}
});
}
-
/**
* called when pasting. it tries to avoid pasting long non spaced strings
* @param linkToCheck
@@ -456,17 +593,326 @@ public class ShareUpdateForm extends Composite {
* add the link preview in the view
* @param result
*/
- private void addPreview(LinkPreview result, boolean isFilePreview) {
+ private void addPreviewLink(LinkPreview result) {
+ preview.clear();
uploadProgress.setVisible(false);
- myLinkPreviewer = new LinkPreviewer(this, result, isFilePreview);
+ myLinkPreviewer = new LinkPreviewer(this, result);
preview.add(myLinkPreviewer);
}
+
+ /**
+ * Call it to show attachment(s)
+ */
+ private void addPreviewAttachment(LinkPreview result, AttachmentPreviewer atPrev){
+
+ uploadProgress.setVisible(false);
+
+ // check the result
+ if(result == null){
+ // failed upload
+ atPrev.setResultAttachment(ATTACHMENT_NOT_LOADED, notLoadedAttachment);
+
+ // change the preview image to reload icon to let the user retry
+ atPrev.setImagePreviewToRetry(RETRY_TO_ATTACH_MESSAGE, retryToAttach);
+ }
+ else{
+ // set the preview information (the first image is the one related to attachments)
+ atPrev.setResultAttachment(ATTACHMENT_LOADED, loadedAttachment);
+ atPrev.setImagePreview(result.getImageUrls().get(0));
+ }
+
+ preview.add(atPrev);
+ }
/**
*
*/
- protected void cancelPreview() {
+ protected void cancelLinkPreview() {
preview.clear();
myLinkPreviewer = null;
attachButton.getElement().getStyle().setVisibility(Visibility.VISIBLE); //beacuse otherwise it looses the other properties setting
}
+
+ /**
+ * Handle drop of files within shareTextArea (native javascript code)
+ * @param instance
+ */
+ private static native void addNativeDropHandler(ShareUpdateForm instance,
+ String servletUrl)/*-{
+
+ console.log("Adding drop handler to text area");
+
+ // retrieve textArea by id
+ var drop = $wnd.$('#postTextArea')[0];
+ console.log("drop is " + drop);
+
+ // check if this file is a folder
+ function isFolder(file) {
+
+ if (file != null && !file.type && file.size % 4096 == 0) {
+ return true;
+ }
+ return false;
+ }
+
+ // function used to add the handler
+ function addEventHandler(obj, evt, handler) {
+ if (obj.addEventListener) {
+ // W3C method
+ obj.addEventListener(evt, handler, false);
+ } else if (obj.attachEvent) {
+ // IE method.
+ obj.attachEvent('on' + evt, handler);
+ } else {
+ // Old school method.
+ obj['on' + evt] = handler;
+ }
+ }
+
+ // The real drop handler
+ addEventHandler(
+ drop,
+ 'drop',
+ function(e) {
+
+ // get window.event if e argument missing (in IE)
+ e = e || window.event;
+
+ // stops the browser from redirecting off to the image.
+ if (e.preventDefault) {
+
+ e.preventDefault();
+
+ }
+
+ // opts for the remote call
+ var opts = {
+
+ url : servletUrl,
+ type : "POST",
+ processData : false
+
+ };
+
+ // get the file(s)
+ var dt = e.dataTransfer;
+ var files = dt.files;
+
+ // check limit for number of files
+ var numberOfAlreadyAttachedFiles = instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::numberOfAttachments()();
+ numberOfAlreadyAttachedFiles += files.length;
+ var limitExceeded = (files.length > @org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::MAX_NUMBER_ATTACHMENTS);
+
+ if(limitExceeded){
+
+ var msg = "Too much files attached!"
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::showAlert(Ljava/lang/String;)(msg);
+ console.log(msg);
+
+ // reset text area
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::resetTextArea()();
+ return;
+ }
+
+ // reset if no file was dropped (??)
+ if (files.length == 0) {
+
+ // reset text area
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::resetTextArea()();
+ return;
+
+ }
+
+ console.log("Number of dropped file(s): " + files.length);
+
+ var numFolder = 0;
+
+ // save maximum allowed size
+ var maximumSize = @org.gcube.portlets.widgets.fileupload.client.view.FileSubmit::MAX_SIZE_ATTACHED_FILE_MB;
+
+ // msg for ignored (too big files)
+ var ignoredFilesAlert = " file(s) ignored because larger than " + maximumSize + "MB";
+
+ // number of ignored files
+ var numberIgnoredFiles = 0;
+
+ // for each dropped file
+ for (var i = 0; i < files.length; i++) {
+
+ var file = files[i];
+ var fileSelected = file.name + ";";
+
+ // be sure it is not a folder
+ if (!isFolder(file)) {
+ console.log("filesSelected: " + fileSelected);
+ console.log("files: " + files);
+
+ // check its size
+ var fileSize = file.size / 1024 / 1024;
+
+ console.log("File size is " + fileSize);
+
+ if(fileSize > maximumSize){
+ numberIgnoredFiles ++;
+ continue;
+ }
+
+ // create new progress bar
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::showProgressDND()();
+
+ // create request
+ var xhr = new XMLHttpRequest();
+ xhr.open(opts.type, opts.url, true);
+ var formdata = new FormData();
+
+ // append the file
+ formdata.append("fileUpload", file);
+
+ // send data
+ xhr.send(formdata);
+
+ console.log("File " + file.name + " sent at " + servletUrl);
+
+ }else{
+
+ // increment the number of skipped folders
+ numFolder++;
+
+ }
+ }
+
+ // alert the user that folder(s) can't be uploaded
+ if(numFolder > 0){
+ var msg;
+
+ if(numFolder == files.length){
+
+ msg = "Sorry but it's not possible to upload a folder!";
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::showAlert(Ljava/lang/String;)(msg);
+
+ // reset text area
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::resetTextArea()();
+ return;
+
+ }
+
+ // print ignored folders, if any
+ var msg = "Ignored ";
+ msg += numFolder > 1? numFolder+" folders": numFolder+" folder";
+ msg+= " during upload.";
+ console.log(msg);
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::showAlert(Ljava/lang/String;)(msg);
+ }
+
+ // alert for too large files
+ if(numberIgnoredFiles > 0){
+ var msg = numberIgnoredFiles + ignoredFilesAlert;
+
+ if(numberIgnoredFiles == files.length){
+
+ msg = file.name + " can't be uploaded since it is too large!";
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::showAlert(Ljava/lang/String;)(msg);
+
+ // reset text area
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::resetTextArea()();
+ return;
+
+ }
+
+ var msg = numberIgnoredFiles + ignoredFilesAlert;
+ console.log(msg);
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::showAlert(Ljava/lang/String;)(msg);
+ }
+
+ // reset text area
+ instance.@org.gcube.portlets.user.shareupdates.client.view.ShareUpdateForm::resetTextArea()();
+ });
+
+ }-*/;
+
+ /**
+ * Check if DND could be enabled (i.e, it's supported by the browser)
+ * @return
+ */
+ public static native boolean checkDNDAvailability()/*-{
+
+ return window.FileReader;
+
+ }-*/;
+
+ /**
+ * On dragLeave reset changes on the text area
+ */
+ private void resetTextArea() {
+
+ // remove border properties
+ shareTextArea.getElement().getStyle().setBorderStyle(BorderStyle.SOLID);
+ shareTextArea.getElement().getStyle().setBorderColor("#333");
+ shareTextArea.getElement().getStyle().setBorderWidth(1, Unit.PX);
+
+ // change back background color
+ shareTextArea.getElement().getStyle().setBackgroundColor("transparent");
+
+ // remove text "Drop file here" and reput the old text
+ shareTextArea.setText(previousText);
+ shareTextArea.setAlignment(TextAlignment.LEFT);
+
+ // rechange text color if needed
+ if(!previousText.equals(DROP_FILE_HERE_TEXT) && !previousText.equals(SHARE_UPDATE_TEXT))
+ shareTextArea.getElement().getStyle().setColor("#333");
+
+ // reset padding top
+ shareTextArea.getElement().getStyle().setPaddingTop(4, Unit.PX);
+
+ // reset font weight
+ shareTextArea.getElement().getStyle().setFontWeight(FontWeight.NORMAL);
+ }
+
+ /**
+ * Alert the user about something.
+ *
+ * @param msg the msg to show
+ */
+ private void showAlert(String msg){
+
+ Window.alert(msg);
+
+ }
+
+ /**
+ * Show progress bar and start the ProgressController
+ * @param e
+ */
+ private void showProgressDND() {
+ uploadProgress.initializeDND();
+ uploadProgress.setVisible(true);
+ }
+
+ /**
+ * Remove an attached file from the listOfAttachedFiles
+ * @param attachmentPreviewer
+ */
+ public void removeAttachedFile(AttachmentPreviewer attachmentPreviewer) {
+
+ Iterator iterator = listOfAttachedFiles.iterator();
+
+ while (iterator.hasNext()) {
+ AttachedFile attachedFile = (AttachedFile) iterator.next();
+ if(attachedFile.getAtPrev().equals(attachedFile)){
+ iterator.remove();
+ return;
+ }
+
+ }
+
+ }
+
+ /**
+ * Get the number of attached files
+ * @return number of attached files
+ */
+ public int numberOfAttachments(){
+
+ return listOfAttachedFiles.size();
+
+ }
}
diff --git a/src/main/java/org/gcube/portlets/user/shareupdates/shared/LinkPreview.java b/src/main/java/org/gcube/portlets/user/shareupdates/shared/LinkPreview.java
index 5e99d68..5bbad9e 100644
--- a/src/main/java/org/gcube/portlets/user/shareupdates/shared/LinkPreview.java
+++ b/src/main/java/org/gcube/portlets/user/shareupdates/shared/LinkPreview.java
@@ -4,6 +4,11 @@ import java.io.Serializable;
import java.util.ArrayList;
@SuppressWarnings("serial")
+/**
+ * This class is used for link preview (both actual links and attachments)
+ * @author Costantino Perciante at ISTI-CNR
+ *
+ */
public class LinkPreview implements Serializable {
private String title;
diff --git a/src/main/webapp/ShareUpdates.css b/src/main/webapp/ShareUpdates.css
index d08da4f..84b8e78 100644
--- a/src/main/webapp/ShareUpdates.css
+++ b/src/main/webapp/ShareUpdates.css
@@ -1,4 +1,4 @@
-td > form {
+td>form {
margin-top: 5px !important;
margin-bottom: 0px !important;
}
@@ -9,7 +9,7 @@ fieldset {
}
fieldset .control-group {
- margin-bottom: 0px;
+ margin-bottom: 0px;
}
fieldset select {
@@ -135,7 +135,7 @@ fieldset select {
padding: 5px 15px;
}
-.shareButton:hover,.shareButton:focus {
+.shareButton:hover, .shareButton:focus {
background-color: #019AD3;
background-image: linear-gradient(#33BCEF, #019AD3);
border-color: #057ED0;
@@ -220,6 +220,21 @@ fieldset select {
cursor: hand;
}
+.su-deleteAttachment {
+ background: url(images/close.png) 0px 0px no-repeat;
+ height: 15px;
+ width: 15px;
+ display: inline;
+ float: right;
+ vertical-align: top;
+}
+
+.su-deleteAttachment:hover {
+ background: url(images/close.png) 0px -16px no-repeat;
+ cursor: pointer;
+ cursor: hand;
+}
+
.su-closeImage:active {
background: url(images/close.png) 0px -32px no-repeat;
}
@@ -242,7 +257,7 @@ fieldset select {
cursor: hand;
}
-a.link,a.link:active,a.link:visited {
+a.link, a.link:active, a.link:visited {
font-family: 'Lucida Grande', Verdana, 'Bitstream Vera Sans', Arial,
sans-serif;
font-size: 12px;
diff --git a/src/main/webapp/images/attachment_default.png b/src/main/webapp/images/attachment_default.png
new file mode 100644
index 0000000..b0e0695
Binary files /dev/null and b/src/main/webapp/images/attachment_default.png differ
diff --git a/src/main/webapp/images/load.png b/src/main/webapp/images/load.png
new file mode 100644
index 0000000..31bd433
Binary files /dev/null and b/src/main/webapp/images/load.png differ
diff --git a/src/main/webapp/images/not_load.png b/src/main/webapp/images/not_load.png
new file mode 100644
index 0000000..23b4d00
Binary files /dev/null and b/src/main/webapp/images/not_load.png differ
diff --git a/src/main/webapp/images/reload.png b/src/main/webapp/images/reload.png
new file mode 100644
index 0000000..df4107d
Binary files /dev/null and b/src/main/webapp/images/reload.png differ