Merge branch 'master' of https://code.grnet.gr/git/pithos-web-client
[pithos-web-client] / src / gr / grnet / pithos / web / client / FileUploadDialog.java
1 /*
2  * Copyright 2011-2013 GRNET S.A. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or
5  * without modification, are permitted provided that the following
6  * conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above
9  *      copyright notice, this list of conditions and the following
10  *      disclaimer.
11  *
12  *   2. Redistributions in binary form must reproduce the above
13  *      copyright notice, this list of conditions and the following
14  *      disclaimer in the documentation and/or other materials
15  *      provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  *
30  * The views and conclusions contained in the software and
31  * documentation are those of the authors and should not be
32  * interpreted as representing official policies, either expressed
33  * or implied, of GRNET S.A.
34  */
35 package gr.grnet.pithos.web.client;
36
37 import gr.grnet.pithos.web.client.foldertree.Folder;
38
39 import com.google.gwt.core.client.Scheduler;
40 import com.google.gwt.dom.client.NativeEvent;
41 import com.google.gwt.event.dom.client.ClickEvent;
42 import com.google.gwt.event.dom.client.ClickHandler;
43 import com.google.gwt.event.dom.client.KeyCodes;
44 import com.google.gwt.user.client.Command;
45 import com.google.gwt.user.client.Event.NativePreviewEvent;
46 import com.google.gwt.user.client.ui.Anchor;
47 import com.google.gwt.user.client.ui.Button;
48 import com.google.gwt.user.client.ui.DialogBox;
49 import com.google.gwt.user.client.ui.FileUpload;
50 import com.google.gwt.user.client.ui.FlowPanel;
51 import com.google.gwt.user.client.ui.FormPanel;
52 import com.google.gwt.user.client.ui.Grid;
53 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
54 import com.google.gwt.user.client.ui.Hidden;
55 import com.google.gwt.user.client.ui.HorizontalPanel;
56 import com.google.gwt.user.client.ui.Label;
57 import com.google.gwt.user.client.ui.VerticalPanel;
58
59 /**
60  * The 'File upload' dialog box implementation.
61  */
62 public class FileUploadDialog extends DialogBox {
63
64     public static final boolean DONE = true;
65
66     Anchor close;
67     
68         /**
69          * The Form element that performs the file upload.
70          */
71     protected final FormPanel form = new FormPanel();
72
73         private final FileUpload upload = new FileUpload();
74
75         private final Label filenameLabel = new Label();
76
77     private final Label foldernameLabel = new Label();
78
79     private Button submit;
80
81         protected Folder folder;
82
83     protected Pithos app;
84     
85     private boolean inProgress = false;
86
87         /**
88          * The widget's constructor.
89          */
90         public FileUploadDialog(Pithos _app) {
91                 app = _app;
92                 close = new Anchor("close");
93                 close.addStyleName("close");
94                 close.addClickHandler(new ClickHandler() {
95                         
96                         @Override
97                         public void onClick(ClickEvent event) {
98                                 close();
99                         }
100                 });
101                 // Set the dialog's caption.
102                 setText("File upload");
103                 setStyleName("pithos-DialogBox");
104                 setVisible(false);
105                 
106                 // Since we're going to add a FileUpload widget, we'll need to set the
107                 // form to use the POST method, and multipart MIME encoding.
108                 form.setEncoding(FormPanel.ENCODING_MULTIPART);
109                 form.setMethod(FormPanel.METHOD_POST);
110
111                 // Create a panel to hold all of the form widgets.
112                 VerticalPanel panel = new VerticalPanel();
113                 panel.setWidth("470px");
114                 panel.add(close);
115                 form.setWidget(panel);
116
117                 VerticalPanel inner = new VerticalPanel();
118                 inner.addStyleName("inner");
119
120         final Hidden auth = new Hidden("X-Auth-Token");
121         inner.add(auth);
122                 upload.setName("X-Object-Data");
123                 upload.setVisible(false);
124                 filenameLabel.setText("");
125                 filenameLabel.setVisible(false);
126                 filenameLabel.setStyleName("props-labels");
127                 HorizontalPanel fileUploadPanel = new HorizontalPanel();
128                 fileUploadPanel.setVisible(false);
129                 fileUploadPanel.add(filenameLabel);
130                 fileUploadPanel.add(upload);
131                 Grid generalTable = new Grid(2, 2);
132                 generalTable.setText(0, 0, "Folder");
133         generalTable.setWidget(0, 1, foldernameLabel);
134                 generalTable.setWidget(1, 1, fileUploadPanel);
135                 generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");
136         generalTable.getCellFormatter().setStyleName(0, 1, "props-values");
137         generalTable.getCellFormatter().setVisible(1, 0, false);
138                 generalTable.setCellSpacing(4);
139
140                 inner.add(generalTable);
141
142                 FlowPanel uploader = new FlowPanel();
143                 uploader.getElement().setId("uploader");
144                 inner.add(uploader);
145                 
146                 panel.add(inner);
147                 panel.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
148                 
149                 setWidget(form);
150                 
151                 Scheduler.get().scheduleDeferred(new Scheduler.ScheduledCommand() {
152                         
153                         @Override
154                         public void execute() {
155                                 center();
156                                 close();
157                         }
158                 });
159         }
160
161         private void refreshFolder() {
162                 if (app.getSelectedTree().equals(app.getFolderTreeView()))
163                         app.updateFolder(folder, true, new Command() {
164                                 
165                                 @Override
166                                 public void execute() {
167                                         app.updateStatistics();
168                                 }
169                         }, true);
170                 else
171                         app.updateOtherSharedFolder(folder, true, null);
172         }
173         
174         native void setupUpload(FileUploadDialog dlg, Pithos app, String token) /*-{
175                 var uploader = $wnd.$('#uploader').pluploadQueue();
176                 var createUploader = function() {
177                         $wnd.$("#uploader").pluploadQueue({
178                                 // General settings
179                                 runtimes : 'html5, flash, gears, silverlight, browserplus, html4',
180                                 unique_names : true,
181                 
182                                 // Flash settings
183                                 flash_swf_url : 'plupload/js/plupload.flash.swf',
184                 
185                                 // Silverlight settings
186                                 silverlight_xap_url : 'plupload/js/plupload.silverlight.xap',
187                                 
188                                 multiple_queues: true,
189                                 
190                                 preinit: {
191                                         Init: function(up, info) {
192                                                 if ($wnd.console && $wnd.console.log)
193                                                         $wnd.console.log("Init fired");
194                                                 up.settings.file_data_name = "X-Object-Data";                           
195                                         }
196                                         
197                                 },
198                                 
199                                 init: {
200                                         FilesAdded: function(up, files) {
201                                                 var api = app.@gr.grnet.pithos.web.client.Pithos::getApiPath()();
202                                                 var folder = app.@gr.grnet.pithos.web.client.Pithos::getUploadFolder()();
203                                                 var owner = folder.@gr.grnet.pithos.web.client.foldertree.Folder::getOwnerID()();
204                                                 var uri = folder.@gr.grnet.pithos.web.client.foldertree.Folder::getUri()();
205                                                 var path = api + owner + uri;
206                                                 for (var j=0; j<files.length; j++)
207                                                         files[j].url = path + "/" + files[j].name;
208                                                 dlg.@gr.grnet.pithos.web.client.FileUploadDialog::setInProgress(Z)(true);
209                                                 if (up.state == $wnd.plupload.STOPPED)
210                                                         up.start();
211                                                 app.@gr.grnet.pithos.web.client.Pithos::showUploadIndicator()();
212                                                 if (!dlg.@gr.grnet.pithos.web.client.FileUploadDialog::isVisible()())
213                                                         app.@gr.grnet.pithos.web.client.Pithos::showUploadAlert(I)(up.files.length);
214                                         },
215                                         
216                                         FilesRemoved: function(up, files) {
217                                                 if (up.files.length == 0)
218                                                         dlg.@gr.grnet.pithos.web.client.FileUploadDialog::setInProgress(Z)(false);
219                                                 else
220                                                         dlg.@gr.grnet.pithos.web.client.FileUploadDialog::setInProgress(Z)(true);
221                                         },
222                                         
223                                         BeforeUpload: function(up, file) {
224                                                 if ($wnd.console && $wnd.console.log)
225                                                         $wnd.console.log('About to upload ' + file.url);
226                                                 up.settings.url = file.url + + "?X-Auth-Token=" + encodeURIComponent(token);
227                                         },
228                                         
229                                         UploadProgress: function(up, file) {
230                                                 $wnd.$('#upload_alert_progress_bar').css('width', up.total.percent + '%');
231                                                 $wnd.$('#upload_alert_percent').html(up.total.percent + '%');
232                                         },
233                                         
234                                         FileUploaded: function(up, file, response) {
235                                                 if ($wnd.console && $wnd.console.log) {
236                                                         $wnd.console.log('File ' + file.name + ' uploaded');
237                                                         $wnd.console.log('Response: ' + response);
238                                                 }
239                                                 var folder = app.@gr.grnet.pithos.web.client.Pithos::getUploadFolder()();
240                                                 if (folder == file.folder)
241                                                         app.@gr.grnet.pithos.web.client.Pithos::updateUploadFolder()();
242                                         },
243                                         
244                                         UploadComplete: function(up, files) {
245                                                 if ($wnd.console && $wnd.console.log) {
246                                                         $wnd.console.log('All files finished');
247                                                 }
248                                                 dlg.@gr.grnet.pithos.web.client.FileUploadDialog::setInProgress(Z)(false);
249                                                 dlg.@gr.grnet.pithos.web.client.FileUploadDialog::hideUploadIndicator()();
250                                                 app.@gr.grnet.pithos.web.client.Pithos::hideUploadAlert()();
251                                                 var uris = [];
252                                                 if (!dlg.@gr.grnet.pithos.web.client.FileUploadDialog::isVisible()())
253                                                         while (files.length > 0) {
254                                                                 uris.push(files[0].url);
255                                                                 up.removeFile(files[0]);
256                                                         }
257                                                 else
258                                                         for (var i=0; i<files.length; i++)
259                                                                 uris.push(files[i].url);
260                                                 app.@gr.grnet.pithos.web.client.Pithos::updateUploadFolder(Lcom/google/gwt/core/client/JsArrayString;)(uris);
261                                         },
262                                         
263                                         Error: function(up, error) {
264                                                 if ($wnd.console && $wnd.console.log)
265                                                         $wnd.console.log("Error occured:" + error);
266                                         }
267                                 }
268                         });
269                         return $wnd.$('#uploader').pluploadQueue();
270                 };
271                 
272                 if ($wnd.console && $wnd.console.log)
273                         $wnd.console.log(uploader);
274                 if (!uploader) {
275                         uploader = createUploader();
276                 }
277                 else {
278                         var dropElm = $wnd.document.getElementById('rightPanel');
279                         $wnd.plupload.removeAllEvents(dropElm, uploader.id);
280                         var removeAll = true;
281                         var files = uploader.files;
282                         if ($wnd.console && $wnd.console.log)
283                                 $wnd.console.log('About to check ' + files.length + ' files');
284                         for (var i=0; i<files.length; i++) {
285                                 var f = files[i];
286                                 if (f.status != $wnd.plupload.DONE && f.status != $wnd.plupload.FAILED) {
287                                         removeAll = false;
288                                         break;
289                                 }
290                         }
291                         if (removeAll) {
292                                 if ($wnd.console && $wnd.console.log)
293                                         $wnd.console.log('About to remove ' + files.length + ' files');
294                                 uploader.destroy();
295                                 uploader = createUploader();
296                                 if ($wnd.console && $wnd.console.log)
297                                         $wnd.console.log(uploader);
298                                 dlg.@gr.grnet.pithos.web.client.FileUploadDialog::setInProgress(Z)(false);
299                         }
300                         else {
301                                 dlg.@gr.grnet.pithos.web.client.FileUploadDialog::setInProgress(Z)(true);
302                         }
303                 }
304         }-*/;
305         
306         native boolean isUploading()/*-{
307                 var uploader = $wnd.$("#uploader").pluploadQueue();
308                 var files = uploader.files;
309                 for (var i=0; i<files.length; i++) {
310                         var f = files[i];
311                         if (f.status == $wnd.plupload.UPLOADING) {
312                                 return true;
313                         }
314                 }
315                 return false;
316         }-*/;
317         
318         @Override
319         protected void onPreviewNativeEvent(NativePreviewEvent event) {
320                 super.onPreviewNativeEvent(event);
321
322                 NativeEvent evt = event.getNativeEvent();
323                 if (evt.getType().equals("keydown"))
324                         // Use the popup's key preview hooks to close the dialog when
325                         // escape is pressed.
326                         switch (evt.getKeyCode()) {
327                                 case KeyCodes.KEY_ESCAPE:
328                                         close();
329                                         break;
330                         }
331         }
332
333         public void setFolder(Folder folder) {
334                 this.folder = folder;
335                 foldernameLabel.setText(folder.getName());
336         }
337
338         @Override
339         public void center() {
340                 app.hideUploadIndicator();
341                 setVisible(true);
342                 setModal(true);
343                 super.center();
344                 setupUpload(this, app, app.getUserToken());
345                 super.center();
346         }
347         
348         private void hideUploadIndicator() {
349                 app.hideUploadIndicator();
350         }
351         
352         void close() {
353                 setVisible(false);
354                 setModal(false);
355                 clearUploader();
356                 if (isUploading())
357                         app.showUploadIndicator();
358                 setGlobalDropArea();
359         }
360
361         private native void clearUploader() /*-{
362                 var uploader = $wnd.$("#uploader").pluploadQueue();
363                 var files = uploader.files;
364                 var clear = true;
365                 for (var i=0; i<files.length; i++)
366                         if (files[i].status == $wnd.plupload.UPLOADING)
367                                 clear = false;
368                 if (clear)
369                         while (files.length > 0)
370                                 uploader.removeFile(files[0]);
371         }-*/;
372         
373         native void setGlobalDropArea() /*-{
374                 var uploader = $wnd.$("#uploader").pluploadQueue();
375                 if (uploader.runtime == 'html5') {
376                         uploader.settings.drop_element = 'rightPanel';
377                         uploader.trigger('PostInit');
378                 }
379         }-*/;
380
381         private void setInProgress(boolean _inProgress) {
382                 inProgress = _inProgress;
383                 if (inProgress)
384                         close.setText("hide");
385                 else
386                         close.setText("close");
387         }
388 }