Use Lytebox (a Lightbox clone) for quick viewing images.
[pithos] / src / gr / ebs / gss / client / FileUploadGearsDialog.java
index fb843be..25203a8 100644 (file)
@@ -26,7 +26,9 @@ import gr.ebs.gss.client.rest.resource.FolderResource;
 \r
 import java.util.ArrayList;\r
 import java.util.Arrays;\r
+import java.util.HashMap;\r
 import java.util.List;\r
+import java.util.Map;\r
 \r
 import com.google.gwt.core.client.GWT;\r
 import com.google.gwt.gears.client.Factory;\r
@@ -37,16 +39,17 @@ import com.google.gwt.gears.client.httprequest.HttpRequest;
 import com.google.gwt.gears.client.httprequest.ProgressEvent;\r
 import com.google.gwt.gears.client.httprequest.ProgressHandler;\r
 import com.google.gwt.gears.client.httprequest.RequestCallback;\r
+import com.google.gwt.http.client.URL;\r
 import com.google.gwt.json.client.JSONObject;\r
 import com.google.gwt.json.client.JSONString;\r
 import com.google.gwt.user.client.Command;\r
 import com.google.gwt.user.client.DeferredCommand;\r
 import com.google.gwt.user.client.ui.Button;\r
 import com.google.gwt.user.client.ui.ClickListener;\r
-import com.google.gwt.user.client.ui.Grid;\r
+import com.google.gwt.user.client.ui.FlexTable;\r
+import com.google.gwt.user.client.ui.HTML;\r
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
 import com.google.gwt.user.client.ui.HorizontalPanel;\r
-import com.google.gwt.user.client.ui.TextBox;\r
 import com.google.gwt.user.client.ui.VerticalPanel;\r
 import com.google.gwt.user.client.ui.Widget;\r
 \r
@@ -57,9 +60,31 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
 \r
        private final Factory factory = Factory.getInstance();\r
 \r
+       /**\r
+        * The array of files to upload.\r
+        */\r
+       private File[] fileObjects;\r
+\r
+       /**\r
+        * A list of files to upload, created from files array. Used to signal\r
+        * finished state when empty.\r
+        */\r
        private List<File> selectedFiles = new ArrayList<File>();\r
 \r
-       private TextBox selected;\r
+       /**\r
+        * The list of progress bars for individual files.\r
+        */\r
+       private List<ProgressBar> progressBars = new ArrayList<ProgressBar>();\r
+\r
+       private Button browse;\r
+\r
+       private Button submit;\r
+\r
+       private FlexTable generalTable;\r
+\r
+       private Map<String, FileResource> toRename;\r
+\r
+       private List<HttpRequest> requests = new ArrayList<HttpRequest>();\r
 \r
        /**\r
         * The widget's constructor.\r
@@ -70,24 +95,19 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                setAnimationEnabled(true);\r
                // Create a panel to hold all of the dialog widgets.\r
                VerticalPanel panel = new VerticalPanel();\r
+               final HTML info = new HTML("You may select one or more files to upload.");\r
+               info.addStyleName("gss-uploadNote");\r
+               panel.add(info);\r
                // Add an informative label with the folder name.\r
                Object selection = GSS.get().getFolders().getCurrent().getUserObject();\r
                folder = (FolderResource) selection;\r
-               filenameLabel.setText("");\r
-               filenameLabel.setVisible(false);\r
-               filenameLabel.setStyleName("props-labels");\r
-\r
-               final Button browse = new Button("Browse...");\r
 \r
-               selected = new TextBox();\r
-               selected.setEnabled(false);\r
+               browse = new Button("Browse...");\r
 \r
                HorizontalPanel fileUploadPanel = new HorizontalPanel();\r
-               fileUploadPanel.add(filenameLabel);\r
-               fileUploadPanel.add(selected);\r
                fileUploadPanel.add(browse);\r
 \r
-               Grid generalTable = new Grid(2, 2);\r
+               generalTable = new FlexTable();\r
                generalTable.setText(0, 0, "Folder");\r
                generalTable.setText(1, 0, "File");\r
                generalTable.setText(0, 1, folder.getName());\r
@@ -103,26 +123,10 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                // Create a panel to hold the buttons.\r
                HorizontalPanel buttons = new HorizontalPanel();\r
 \r
-               // Create the 'upload' button, along with a listener that submits the\r
-               // form.\r
-               final Button submit = new Button("Upload");\r
+               submit = new Button("Upload");\r
                submit.addClickListener(new ClickListener() {\r
 \r
                        public void onClick(Widget sender) {\r
-                               GSS app = GSS.get();\r
-                               if (selectedFiles.size() == 0) {\r
-                                       app.displayError("You must select a file!");\r
-                                       hide();\r
-                                       return;\r
-                               }\r
-                               for(File file: selectedFiles)\r
-                                       if (!canContinue(file)) {\r
-                                               app.displayError("The specified file name already exists in this folder");\r
-                                               hide();\r
-                                               return;\r
-                                       }\r
-                               submit.setEnabled(false);\r
-                               browse.setVisible(false);\r
                                prepareAndSubmit();\r
                        }\r
                });\r
@@ -134,7 +138,7 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                Button cancel = new Button("Cancel", new ClickListener() {\r
 \r
                        public void onClick(Widget sender) {\r
-                               hide();\r
+                               cancelUpload();\r
                        }\r
                });\r
                buttons.add(cancel);\r
@@ -148,8 +152,17 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                                desktop.openFiles(new OpenFilesHandler() {\r
 \r
                                        public void onOpenFiles(OpenFilesEvent event) {\r
-                                               selectedFiles.addAll(Arrays.asList(event.getFiles()));\r
-                                               selected.setText(selectedFiles.get(0).getName());\r
+                                               fileObjects = event.getFiles();\r
+                                               selectedFiles.addAll(Arrays.asList(fileObjects));\r
+                                               for (int i = 0; i< selectedFiles.size(); i++) {\r
+                                                       generalTable.setText(i+1, 0, "File");\r
+                                                       generalTable.setText(i+1, 1, selectedFiles.get(i).getName());\r
+                                                       ProgressBar progress = new ProgressBar(20, 0);\r
+                                                       generalTable.setWidget(i+1, 2, progress);\r
+                                                       progressBars.add(progress);\r
+                                                       generalTable.getCellFormatter().setStyleName(i+1, 0, "props-labels");\r
+                                                       generalTable.getCellFormatter().setStyleName(i+1, 1, "props-values");\r
+                                               }\r
                                                submit.setEnabled(true);\r
                                        }\r
                                });\r
@@ -157,17 +170,22 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                });\r
 \r
                panel.add(buttons);\r
-               progressBar = new ProgressBar(50, ProgressBar.SHOW_TIME_REMAINING);\r
-               panel.add(progressBar);\r
-               progressBar.setVisible(false);\r
                panel.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER);\r
-               panel.setCellHorizontalAlignment(progressBar, HasHorizontalAlignment.ALIGN_CENTER);\r
                panel.addStyleName("gss-DialogBox");\r
                addStyleName("gss-DialogBox");\r
                setWidget(panel);\r
        }\r
 \r
        /**\r
+        * Cancels the file upload.\r
+        */\r
+       private void cancelUpload() {\r
+               for (HttpRequest request: requests)\r
+                       request.abort();\r
+               hide();\r
+       }\r
+\r
+       /**\r
         * Check whether the specified file name exists in the selected folder.\r
         */\r
        private boolean canContinue(File file) {\r
@@ -181,128 +199,166 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
        }\r
 \r
        @Override\r
-       public void prepareAndSubmit(){\r
-               final String fname = getFilename(selectedFiles.get(0).getName());\r
-               if (getFileForName(fname) == null) {\r
-                       // We are going to create a file, so we check to see if there is a\r
-                       // trashed file with the same name.\r
-                       FileResource same = null;\r
-                       for (FileResource fres : folder.getFiles())\r
-                               if (fres.isDeleted() && fres.getName().equals(fname))\r
-                                       same = fres;\r
-                       if (same == null)\r
-                               uploadFiles();\r
-                       else {\r
-                               final FileResource sameFile = same;\r
-                               GWT.log("Same deleted file", null);\r
-                               ConfirmationDialog confirm = new ConfirmationDialog("A file " +\r
-                                               "with the same name exists in the trash. If you " +\r
-                                               "continue,<br/>the trashed file  '" + fname +\r
-                                               "' will be renamed automatically for you.", "Continue") {\r
-\r
-                                       @Override\r
-                                       public void cancel() {\r
-                                               FileUploadGearsDialog.this.hide();\r
-                                       }\r
-\r
-                                       @Override\r
-                                       public void confirm() {\r
-                                               updateTrashedFile(getBackupFilename(fname), sameFile);\r
-                                       }\r
-\r
-                               };\r
-                               confirm.center();\r
+       public void prepareAndSubmit() {\r
+               GSS app = GSS.get();\r
+               if (selectedFiles.size() == 0) {\r
+                       app.displayError("You must select a file!");\r
+                       hide();\r
+                       return;\r
+               }\r
+               for (File file: selectedFiles)\r
+                       if (!canContinue(file)) {\r
+                               app.displayError("The file name " + file.getName() +\r
+                                                       " already exists in this folder");\r
+                               hide();\r
+                               return;\r
                        }\r
+               submit.setEnabled(false);\r
+               browse.setVisible(false);\r
+               List<String> toUpdate = new ArrayList<String>();\r
+               toRename = new HashMap<String, FileResource>();\r
+               for (File file: selectedFiles) {\r
+                       String fname = getFilename(file.getName());\r
+                       if (getFileForName(fname) == null) {\r
+                               // We are going to create a file, so we check to see if there is a\r
+                               // trashed file with the same name.\r
+                               FileResource same = null;\r
+                               for (FileResource fres : folder.getFiles())\r
+                                       if (fres.isDeleted() && fres.getName().equals(fname))\r
+                                               same = fres;\r
+                               // In that case add it to the list of files to rename.\r
+                               if (same != null)\r
+                                       toRename.put(getBackupFilename(fname), same);\r
+                       } else\r
+                               // If we are updating a file add it to the list of files to update.\r
+                               toUpdate.add(fname);\r
                }\r
-               else {\r
-                       // We are going to update an existing file, so show a confirmation dialog.\r
+\r
+               if (!toUpdate.isEmpty()) {\r
+                       StringBuffer sb = new StringBuffer();\r
+                       for (String name: toUpdate)\r
+                               sb.append(name).append("<br/>");\r
+                       // We are going to update existing files, so show a confirmation dialog.\r
                        ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +\r
-                                       "you want to update " + fname + "?", "Update"){\r
+                                       "you want to update the following files?<br/><i>" + sb +\r
+                                       "</i>", "Update") {\r
 \r
                                @Override\r
                                public void cancel() {\r
-                                       FileUploadGearsDialog.this.hide();\r
+                                       hide();\r
                                }\r
 \r
                                @Override\r
                                public void confirm() {\r
-                                       uploadFiles();\r
+                                       confirmRename();\r
                                }\r
 \r
                        };\r
                        confirm.center();\r
-               }\r
+               } else\r
+                       confirmRename();\r
        }\r
 \r
-       private void updateTrashedFile(String newName, FileResource trashedFile) {\r
-               JSONObject json = new JSONObject();\r
-               json.put("name", new JSONString(newName));\r
-               PostCommand cf = new PostCommand(trashedFile.getUri() + "?update=", json.toString(), 200) {\r
+       /**\r
+        * Confirm the renames of synonymous files already in the trash.\r
+        */\r
+       private void confirmRename() {\r
+               if (!toRename.isEmpty()) {\r
+                       StringBuffer sb = new StringBuffer();\r
+                       for (FileResource file: toRename.values())\r
+                               sb.append(file.getName()).append("<br/>");\r
+                       ConfirmationDialog confirm = new ConfirmationDialog("Files " +\r
+                                       "with the following names already exist in the trash. If" +\r
+                                       " you continue,<br/>the trashed files will be renamed " +\r
+                                       "automatically for you:<br/><i>" + sb + "</i>", "Continue") {\r
 \r
-                       @Override\r
-                       public void onComplete() {\r
-                               uploadFiles();\r
-                       }\r
+                               @Override\r
+                               public void cancel() {\r
+                                       hide();\r
+                               }\r
 \r
-                       @Override\r
-                       public void onError(Throwable t) {\r
-                               GWT.log("", t);\r
-                               if (t instanceof RestException) {\r
-                                       int statusCode = ((RestException) t).getHttpStatusCode();\r
-                                       if (statusCode == 405)\r
-                                               GSS.get().displayError("You don't have the necessary permissions");\r
-                                       else if (statusCode == 404)\r
-                                               GSS.get().displayError("User in permissions does not exist");\r
-                                       else if (statusCode == 409)\r
-                                               GSS.get().displayError("A file with the same name already exists");\r
-                                       else if (statusCode == 413)\r
-                                               GSS.get().displayError("Your quota has been exceeded");\r
-                                       else\r
-                                               GSS.get().displayError("Unable to modify file:" +((RestException)t).getHttpStatusText());\r
-                               } else\r
-                                       GSS.get().displayError("System error modifying file:" + t.getMessage());\r
-                       }\r
+                               @Override\r
+                               public void confirm() {\r
+                                       updateTrashedFiles();\r
+                               }\r
 \r
-               };\r
-               DeferredCommand.addCommand(cf);\r
+                       };\r
+                       confirm.center();\r
+               } else\r
+                       uploadFiles();\r
        }\r
 \r
        /**\r
-        * Schedule the PUT requests to upload the files.\r
+        * Rename the conflicting trashed files with the supplied new names.\r
+        */\r
+       private void updateTrashedFiles() {\r
+               for (final String name: toRename.keySet()) {\r
+                       JSONObject json = new JSONObject();\r
+                       json.put("name", new JSONString(name));\r
+                       PostCommand cf = new PostCommand(toRename.get(name).getUri() + "?update=", json.toString(), 200) {\r
+\r
+                               @Override\r
+                               public void onComplete() {\r
+                                       toRename.remove(name);\r
+                                       uploadFiles();\r
+                               }\r
+\r
+                               @Override\r
+                               public void onError(Throwable t) {\r
+                                       GSS app = GSS.get();\r
+                                       GWT.log("", t);\r
+                                       if (t instanceof RestException) {\r
+                                               int statusCode = ((RestException) t).getHttpStatusCode();\r
+                                               if (statusCode == 405)\r
+                                                       app.displayError("You don't have the necessary permissions");\r
+                                               else if (statusCode == 404)\r
+                                                       app.displayError("User in permissions does not exist");\r
+                                               else if (statusCode == 409)\r
+                                                       app.displayError("A file with the same name already exists");\r
+                                               else if (statusCode == 413)\r
+                                                       app.displayError("Your quota has been exceeded");\r
+                                               else\r
+                                                       app.displayError("Unable to modify file:" + ((RestException) t).getHttpStatusText());\r
+                                       } else\r
+                                               app.displayError("System error modifying file:" + t.getMessage());\r
+                               }\r
+\r
+                       };\r
+                       DeferredCommand.addCommand(cf);\r
+               }\r
+       }\r
+\r
+       /**\r
+        * Checks if the renaming step for already trashed files is complete and\r
+        * starts file uploads.\r
         */\r
        private void uploadFiles() {\r
-               for (final File file: selectedFiles)\r
+               if (!toRename.isEmpty()) return;\r
+               for (int i = 0; i< fileObjects.length; i++) {\r
+                       final int index = i;\r
                        DeferredCommand.addCommand(new Command() {\r
                                public void execute() {\r
-                                       doPut(file);\r
+                                       doPut(fileObjects[index], index);\r
                                }\r
                        });\r
+               }\r
        }\r
 \r
        /**\r
         * Perform the HTTP PUT requests to upload the specified file.\r
         */\r
-       protected void doPut(final File file) {\r
-               GSS app = GSS.get();\r
+       protected void doPut(final File file, final int index) {\r
+               final GSS app = GSS.get();\r
                HttpRequest request = factory.createHttpRequest();\r
+               requests.add(request);\r
                String method = "PUT";\r
 \r
-               fileNameToUse = getFilename(file.getName());\r
-               selected.setVisible(false);\r
-               filenameLabel.setText(fileNameToUse);\r
-               filenameLabel.setVisible(true);\r
-               progressBar.setVisible(true);\r
-\r
                String path;\r
-               FileResource selectedResource = getFileForName(fileNameToUse);\r
-               if (selectedResource == null ) {\r
-                       // We are going to create a file.\r
-                       path = folder.getUri();\r
-                       if (!path.endsWith("/"))\r
-                               path = path + "/";\r
-                       path = path + encodeComponent(fileNameToUse);\r
-               } else\r
-                       path = selectedResource.getUri();\r
+               final String filename = getFilename(file.getName());\r
+               path = folder.getUri();\r
+               if (!path.endsWith("/"))\r
+                       path = path + "/";\r
+               path = path + encode(filename);\r
 \r
                String token = app.getToken();\r
                String resource = path.substring(app.getApiPath().length()-1, path.length());\r
@@ -324,7 +380,21 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                                                SessionExpiredDialog dlg = new SessionExpiredDialog();\r
                                                dlg.center();\r
                                                break;\r
+                                       case 405:\r
+                                               app.displayError("You don't have permission to " +\r
+                                                               "upload file " + filename);\r
+                                               break;\r
+                                       case 409:\r
+                                               app.displayError("A folder with the name " + filename +\r
+                                                               " already exists at this level");\r
+                                               break;\r
+                                       case 413:\r
+                                               app.displayError("There is not enough free space " +\r
+                                                               "available for uploading " + filename);\r
+                                               break;\r
                                        default:\r
+                                               app.displayError("Error uploading file " + filename +\r
+                                                                       ": " + req.getStatus());\r
                                                DisplayHelper.log(req.getStatus() + ":" + req.getStatusText());\r
                                }\r
                        }\r
@@ -332,7 +402,7 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                request.getUpload().setProgressHandler(new ProgressHandler() {\r
                        public void onProgress(ProgressEvent event) {\r
                                double pcnt = (double) event.getLoaded() / event.getTotal();\r
-                               progressBar.setProgress((int) Math.floor(pcnt * 100));\r
+                               progressBars.get(index).setProgress((int) Math.floor(pcnt * 100));\r
                        }\r
                });\r
                request.send(file.getBlob());\r
@@ -347,4 +417,15 @@ public class FileUploadGearsDialog extends FileUploadDialog implements Updateabl
                GSS.get().showFileList(true);\r
                GSS.get().getStatusPanel().updateStats();\r
        }\r
+\r
+       /**\r
+        * Same as URL.encode, but also encode apostrophe since browsers aren't\r
+        * consistent about it (FF encodes, IE does not).\r
+        */\r
+       private String encode(String decodedURL) {\r
+               String retv = URL.encode(decodedURL);\r
+               retv = retv.replaceAll("'", "%27");\r
+               return retv;\r
+       }\r
+\r
 }\r