Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FileUploadDialog.java @ 2f807846

History | View | Annotate | Download (13.3 kB)

1
/*
2
 * Copyright 2011 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.File;
38
import gr.grnet.pithos.web.client.foldertree.Folder;
39

    
40
import com.google.gwt.core.client.GWT;
41
import com.google.gwt.core.client.Scheduler;
42
import com.google.gwt.dom.client.DivElement;
43
import com.google.gwt.dom.client.NativeEvent;
44
import com.google.gwt.event.dom.client.ClickEvent;
45
import com.google.gwt.event.dom.client.ClickHandler;
46
import com.google.gwt.event.dom.client.KeyCodes;
47
import com.google.gwt.user.client.Command;
48
import com.google.gwt.user.client.Cookies;
49
import com.google.gwt.user.client.DOM;
50
import com.google.gwt.user.client.Event.NativePreviewEvent;
51
import com.google.gwt.user.client.Window;
52
import com.google.gwt.user.client.ui.Button;
53
import com.google.gwt.user.client.ui.DialogBox;
54
import com.google.gwt.user.client.ui.FileUpload;
55
import com.google.gwt.user.client.ui.FormPanel;
56
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
57
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
58
import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
59
import com.google.gwt.user.client.ui.FormPanel.SubmitHandler;
60
import com.google.gwt.user.client.ui.Anchor;
61
import com.google.gwt.user.client.ui.Grid;
62
import com.google.gwt.user.client.ui.HTML;
63
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
64
import com.google.gwt.user.client.ui.Hidden;
65
import com.google.gwt.user.client.ui.HorizontalPanel;
66
import com.google.gwt.user.client.ui.Label;
67
import com.google.gwt.user.client.ui.VerticalPanel;
68

    
69
/**
70
 * The 'File upload' dialog box implementation.
71
 */
72
public class FileUploadDialog extends DialogBox {
73

    
74
    public static final boolean DONE = true;
75

    
76
        /**
77
         * The Form element that performs the file upload.
78
         */
79
    protected final FormPanel form = new FormPanel();
80

    
81
        private final FileUpload upload = new FileUpload();
82

    
83
        private final Label filenameLabel = new Label();
84

    
85
    private final Label foldernameLabel = new Label();
86

    
87
    private Button submit;
88

    
89
        protected Folder folder;
90

    
91
    protected Pithos app;
92

    
93
        /**
94
         * The widget's constructor.
95
         */
96
        public FileUploadDialog() {
97
                Anchor close = new Anchor();
98
                close.addStyleName("close");
99
                close.addClickHandler(new ClickHandler() {
100
                        
101
                        @Override
102
                        public void onClick(ClickEvent event) {
103
                                hide();
104
                        }
105
                });
106
                // Set the dialog's caption.
107
                setText("File upload");
108
                setAnimationEnabled(true);
109
                setGlassEnabled(true);
110
                setStyleName("pithos-DialogBox");
111
                // Since we're going to add a FileUpload widget, we'll need to set the
112
                // form to use the POST method, and multipart MIME encoding.
113
                form.getElement().setId("fileupload");
114
                form.setEncoding(FormPanel.ENCODING_MULTIPART);
115
                form.setMethod(FormPanel.METHOD_POST);
116
                // Create a panel to hold all of the form widgets.
117
                VerticalPanel panel = new VerticalPanel();
118
                panel.add(close);
119
                form.setWidget(panel);
120

    
121
                VerticalPanel inner = new VerticalPanel();
122
                inner.addStyleName("inner");
123

    
124
        final Hidden auth = new Hidden("X-Auth-Token");
125
        inner.add(auth);
126
                upload.setName("X-Object-Data");
127
                upload.getElement().setId("fileupload");
128
                upload.getElement().setAttribute("multiple", "");
129
                filenameLabel.setText("");
130
                filenameLabel.setVisible(false);
131
                filenameLabel.setStyleName("props-labels");
132
                HorizontalPanel fileUploadPanel = new HorizontalPanel();
133
                fileUploadPanel.add(filenameLabel);
134
                fileUploadPanel.add(upload);
135
                Grid generalTable = new Grid(2, 2);
136
                generalTable.setText(0, 0, "Folder");
137
        generalTable.setWidget(0, 1, foldernameLabel);
138
                generalTable.setText(1, 0, "File");
139
                generalTable.setWidget(1, 1, fileUploadPanel);
140
                generalTable.getCellFormatter().setStyleName(0, 0, "props-labels");
141
        generalTable.getCellFormatter().setStyleName(0, 1, "props-values");
142
                generalTable.getCellFormatter().setStyleName(1, 0, "props-labels");
143
                generalTable.getCellFormatter().setStyleName(1, 1, "props-values");
144
                generalTable.setCellSpacing(4);
145

    
146
                inner.add(generalTable);
147
                
148
                HTML html = new HTML("<div class='row'><div class='span16'><table class='zebra-striped'><tbody class='files'></tbody></table></div></div>");
149
                inner.add(html);
150

    
151
                // Create the 'upload' button, along with a listener that submits the
152
                // form.
153
                submit = new Button("Upload", new ClickHandler() {
154
                        @Override
155
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
156
                                prepareAndSubmit();
157
                        }
158
                });
159
                submit.addStyleName("button");
160
                inner.add(submit);
161

    
162
                Scheduler.get().scheduleDeferred(new Command() {
163
                        
164
                        @Override
165
                        public void execute() {
166
                                String path = app.getApiPath() + folder.getOwner() + folder.getUri();
167
                                setupUpload(path, app.getToken());
168
                        }
169
                });
170
                
171
                // Add an event handler to the form.
172
                form.addSubmitHandler(new SubmitHandler() {
173

    
174
                        @Override
175
                        public void onSubmit(@SuppressWarnings("unused") SubmitEvent event) {
176
//                auth.setValue(app.getToken()); //This is done here because the app object is not available in the constructor
177
//                Cookies.setCookie("X-Auth-Token", app.getToken(), null, "", "/", false);
178
                        }
179
                });
180
                form.addSubmitCompleteHandler(new SubmitCompleteHandler() {
181

    
182
                        @Override
183
                        public void onSubmitComplete(SubmitCompleteEvent event) {
184
                                // When the form submission is successfully completed, this
185
                                // event is fired. Assuming the service returned a response
186
                                // of type text/html, we can get the result text here (see
187
                                // the FormPanel documentation for further explanation).
188
                                String results = event.getResults();
189

    
190
                                // Unfortunately the results are never empty, even in
191
                                // the absense of errors, so we have to check for '<pre></pre>'.
192
                                if (results != null && results.length() > 0 && !results.equalsIgnoreCase("<pre></pre>")) {
193
                                        GWT.log(results, null);
194
                                        app.displayError(results);
195
                                }
196
                                if (app.getSelectedTree().equals(app.getFolderTreeView()))
197
                                        app.updateFolder(folder, true, new Command() {
198
                                                
199
                                                @Override
200
                                                public void execute() {
201
                                                        app.updateStatistics();
202
                                                }
203
                                        });
204
                                else
205
                                        app.updateOtherSharedFolder(folder, true);
206
                                hide();
207
                        }
208
                });
209

    
210
                panel.add(inner);
211
                panel.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
212
                
213
                setWidget(form);
214
        }
215
        
216
        static native void setupUpload(String path, String token) /*-{
217
                //This is to prevent the default browser action for dropped files
218
//                $wnd.$(document).bind('drop dragover', function (e) {
219
//                    e.preventDefault();
220
//                });
221
                
222
//                $wnd.$('#fileupload').fileupload({
223
//                url: '', //The uri to POST to
224
//                type: 'POST', //DEFAULT
225
//                dataType: '', //Nothing is expected from the server
226
//                dropZone: $wnd.$(document), //DEFAULT
227
//                sequentialUploads: true, //false is the default
228
//                send: function (e, data) {
229
//                            $wnd.console.log('send:' + data.files[0].fileName);
230
//                            return true;
231
//                        },
232
//                        submit: function (e, data) {
233
//                            $wnd.console.log('submit:' + data.files[0].fileName);
234
//                            $wnd.$('#fileupload').fileupload('option', 'url', path + '/' + data.files[0].fileName + '?X-Auth-Token=' + token);
235
//                            return true;
236
//                        },
237
//                done: function (e, data) {
238
//                        $wnd.console.log(data.textStatus + ' ' + data.url);
239
////                    $wnd.$.each(data.result, function (index, file) {
240
////                        $wnd.$('<p/>').text(file.name).appendTo(document.body);
241
////                    });
242
//                }
243
//            });
244

245
    'use strict';
246

247
    // Initialize the jQuery File Upload widget:
248
    $wnd.$('#fileupload').fileupload();
249

250
        $wnd.$('#fileupload').fileupload('option', 'url', '');
251
        $wnd.$('#fileupload').fileupload('option', 'dataType', '');
252
        $wnd.$('#fileupload').fileupload('option', 'submit', function (e, data) {
253
                $wnd.console.log('submit:' + data.files[0].fileName);
254
                $wnd.$('#fileupload').fileupload('option', 'url', path + '/' + data.files[0].fileName + '?X-Auth-Token=' + token);
255
                return true;
256
        });
257
        
258
    // Load existing files:
259
    $wnd.$.getJSON($wnd.$('#fileupload').prop('action'), function (files) {
260
        var fu = $wnd.$('#fileupload').data('fileupload'),
261
            template;
262
        fu._adjustMaxNumberOfFiles(-files.length);
263
        template = fu._renderDownload(files)
264
            .appendTo($wnd.$('#fileupload .files'));
265
        // Force reflow:
266
        fu._reflow = fu._transition && template.length &&
267
            template[0].offsetWidth;
268
        template.addClass('in');
269
    });
270

271
    // Enable iframe cross-domain access via redirect page:
272
    var redirectPage = window.location.href.replace(
273
        /\/[^\/]*$/,
274
        '/cors/result.html?%s'
275
    );
276
    $wnd.$('#fileupload').bind('fileuploadsend', function (e, data) {
277
        if (data.dataType.substr(0, 6) === 'iframe') {
278
            var target = $wnd.$('<a/>').prop('href', data.url)[0];
279
            if (window.location.host !== target.host) {
280
                data.formData.push({
281
                    name: 'redirect',
282
                    value: redirectPage
283
                });
284
            }
285
        }
286
    });
287

288
    // Open download dialogs via iframes,
289
    // to prevent aborting current uploads:
290
    $wnd.$('#fileupload .files').delegate(
291
        'a:not([rel^=gallery])',
292
        'click',
293
        function (e) {
294
            e.preventDefault();
295
            $wnd.$('<iframe style="display:none;"></iframe>')
296
                .prop('src', this.href)
297
                .appendTo(document.body);
298
        }
299
    );
300

301
    // Initialize the Bootstrap Image Gallery plugin:
302
    $wnd.$('#fileupload .files').imagegallery();
303

304
        }-*/;
305

    
306
        @Override
307
        protected void onPreviewNativeEvent(NativePreviewEvent preview) {
308
                super.onPreviewNativeEvent(preview);
309

    
310
                NativeEvent evt = preview.getNativeEvent();
311
                if (evt.getType().equals("keydown"))
312
                        // Use the popup's key preview hooks to close the dialog when either
313
                        // enter or escape is pressed.
314
                        switch (evt.getKeyCode()) {
315
                                case KeyCodes.KEY_ENTER:
316
                                        prepareAndSubmit();
317
                                        break;
318
                                case KeyCodes.KEY_ESCAPE:
319
                                        hide();
320
                                        break;
321
                        }
322
        }
323

    
324
        /**
325
         * Make any last minute checks and start the upload.
326
         */
327
        protected void prepareAndSubmit() {
328
        if (upload.getFilename().length() == 0) {
329
            app.displayError("You must select a file!");
330
            return;
331
        }
332
        final String fname = getFilename(upload.getFilename());
333
        String apath = app.getApiPath() + folder.getOwner() + folder.getUri() + "/" + fname + "?X-Auth-Token=" + app.getToken();
334
        form.setAction(apath);
335
        submit.setEnabled(false);
336
        upload.setVisible(false);
337
        filenameLabel.setText(fname);
338
        filenameLabel.setVisible(true);
339

    
340
                if (getFileForName(fname) == null) {
341
            form.submit();
342
                }
343
                else {
344
                        // We are going to update an existing file, so show a confirmation dialog.
345
                        ConfirmationDialog confirm = new ConfirmationDialog("Are you sure " +
346
                                        "you want to update " + fname + "?", "Update") {
347

    
348
                                @Override
349
                                public void cancel() {
350
                                        FileUploadDialog.this.hide();
351
                                }
352

    
353
                                @Override
354
                                public void confirm() {
355
                                        form.submit();
356
                                }
357

    
358
                        };
359
                        confirm.center();
360
                }
361
        }
362

    
363
    /**
364
         * Returns the file name from a potential full path argument. Apparently IE
365
         * insists on sending the full path name of a file when uploading, forcing
366
         * us to trim the extra path info. Since this is only observed on Windows we
367
         * get to check for a single path separator value.
368
         *
369
         * @param name the potentially full path name of a file
370
         * @return the file name without extra path information
371
         */
372
        protected String getFilename(String name) {
373
                int pathSepIndex = name.lastIndexOf("\\");
374
                if (pathSepIndex == -1) {
375
                        pathSepIndex = name.lastIndexOf("/");
376
                        if (pathSepIndex == -1)
377
                                return name;
378
                }
379
                return name.substring(pathSepIndex + 1);
380
        }
381

    
382
        protected File getFileForName(String name){
383
                for (File f : folder.getFiles())
384
                        if (f.getName().equals(name))
385
                                return f;
386
                return null;
387
        }
388

    
389
    public void setApp(Pithos app) {
390
        this.app = app;
391
    }
392

    
393
    public void setFolder(Folder folder) {
394
        this.folder = folder;
395
        foldernameLabel.setText(folder.getName());
396
    }
397
}