Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FileShareDialog.java @ 64d3b76b

History | View | Annotate | Download (21.4 kB)

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 com.google.gwt.http.client.URL;
38
import com.google.gwt.user.client.ui.*;
39
import gr.grnet.pithos.web.client.foldertree.File;
40
import gr.grnet.pithos.web.client.rest.HeadRequest;
41
import gr.grnet.pithos.web.client.rest.PostRequest;
42

    
43
import com.google.gwt.core.client.GWT;
44
import com.google.gwt.core.client.Scheduler;
45
import com.google.gwt.dom.client.NativeEvent;
46
import com.google.gwt.event.dom.client.ClickEvent;
47
import com.google.gwt.event.dom.client.ClickHandler;
48
import com.google.gwt.event.dom.client.KeyCodes;
49
import com.google.gwt.http.client.Response;
50
import com.google.gwt.http.client.UrlBuilder;
51
import com.google.gwt.resources.client.ImageResource;
52
import com.google.gwt.user.client.Command;
53
import com.google.gwt.user.client.Window;
54
import com.google.gwt.user.client.Event.NativePreviewEvent;
55

    
56
import java.util.Map;
57

    
58
/**
59
 * UI for the "Share" command.
60
 */
61
public class FileShareDialog extends AbstractPropertiesDialog {
62
    // For public sharing
63
        private final HorizontalPanel publicPathPanel = new HorizontalPanel();
64
        private final TextBox publicPathText = new TextBox();
65

    
66
    // For private sharing
67
    private final HorizontalPanel privatePathPanel = new HorizontalPanel();
68
    private final TextBox privatePathText = new TextBox();
69
    private final VerticalPanel privatePermSuperPanel = new VerticalPanel();
70
    private PermissionsList permList;
71
        
72
        /**
73
         * An image bundle for this widgets images.
74
         */
75
        public interface PublicSharingImages extends MessagePanel.Images {
76

    
77
                @Source("gr/grnet/pithos/resources/edit_user.png")
78
                ImageResource permUser();
79

    
80
                @Source("gr/grnet/pithos/resources/groups22.png")
81
                ImageResource permGroup();
82

    
83
                @Source("gr/grnet/pithos/resources/editdelete.png")
84
                ImageResource delete();
85
    }
86

    
87
    public interface PrivateSharingImages extends MessagePanel.Images {
88

    
89
        @Source("gr/grnet/pithos/resources/edit_user.png")
90
        ImageResource permUser();
91

    
92
        @Source("gr/grnet/pithos/resources/groups22.png")
93
        ImageResource permGroup();
94

    
95
        @Source("gr/grnet/pithos/resources/delete.gif")
96
        ImageResource delete();
97
    }
98

    
99
    private final File file;
100

    
101
    private final PublicSharingImages publicSharingImages = GWT.create(PublicSharingImages.class);
102
    private final PrivateSharingImages privateSharingImages = GWT.create(PrivateSharingImages.class);
103

    
104
        /**
105
         * The widget's constructor.
106
         */
107
        public FileShareDialog(Pithos _app, File _file) {
108
        super(_app);
109
        file = _file;
110

    
111
                Anchor close = new Anchor("close");
112
                close.addStyleName("close");
113
                close.addClickHandler(new ClickHandler() {
114
                        
115
                        @Override
116
                        public void onClick(ClickEvent event) {
117
                                hide();
118
                        }
119
                });
120
                // Set the dialog's caption.
121
                setText("Share");
122
                setGlassEnabled(true);
123
                setStyleName("pithos-DialogBox");
124

    
125
                // Outer contains inner and buttons.
126
                final VerticalPanel outer = new VerticalPanel();
127
                outer.add(close);
128
                final FocusPanel focusPanel = new FocusPanel(outer);
129
                // Inner contains generalPanel and permPanel.
130
                inner = new VerticalPanel();
131
                inner.addStyleName("inner");
132

    
133
        inner.add(createMainPanel());
134

    
135
        outer.add(inner);
136

    
137
                final Button ok = new Button("OK", new ClickHandler() {
138
                        @Override
139
                        public void onClick(ClickEvent event) {
140
                                closeDialog();
141
                        }
142
                });
143
                ok.addStyleName("button");
144

    
145
        outer.add(ok);
146
        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
147

    
148
        focusPanel.setFocus(true);
149
        setWidget(outer);
150
        }
151

    
152
    private boolean IamOwner() {
153
        return file.getOwnerID().equals(app.getUserID());
154
    }
155

    
156
    private void populatePublicSharingPanel(VerticalPanel publicSharingPanel) {
157
        if(IamOwner()) {
158
            final HorizontalPanel publicCheckPanel = new HorizontalPanel();
159
            publicCheckPanel.setSpacing(8);
160

    
161
            // Check box header
162
            final CheckBox publicCheckBox = new CheckBox();
163
            Label publicCheckTitle = new InlineHTML("<b>Public on the Internet</b>");
164
            Label publicCheckInfo = new Label("Anyone who has the public link can access. No sign-in required.", true);
165

    
166
            publicCheckBox.setValue(isFilePubliclyShared());
167
            publicCheckBox.addClickHandler(new ClickHandler() {
168
                @Override
169
                public void onClick(ClickEvent event) {
170
                    final Boolean published;
171
                    if(publicCheckBox.getValue() != file.isPublished() && IamOwner()) {
172
                        published = publicCheckBox.getValue();
173
                    }
174
                    else {
175
                        published = Boolean.FALSE;
176
                    }
177

    
178
                    updateMetaDataForPublicSharing(published);
179
                }
180
            });
181

    
182
            publicCheckPanel.add(publicCheckBox);
183
            publicCheckPanel.add(publicCheckTitle);
184
            publicCheckPanel.add(publicCheckInfo);
185

    
186
            // Public Link
187
            publicPathPanel.setVisible(false);
188
            publicPathPanel.setWidth(Const.PERCENT_100);
189
            publicPathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
190
            publicPathPanel.add(new Label("Link"));
191
            publicPathPanel.setSpacing(8);
192
            publicPathPanel.addStyleName("pithos-TabPanelBottom");
193

    
194
            publicPathText.setWidth(Const.PERCENT_100);
195
            publicPathText.addClickHandler(new ClickHandler() {
196
                @Override
197
                public void onClick(ClickEvent event) {
198
                    Pithos.enableIESelection();
199
                    ((TextBox) event.getSource()).selectAll();
200
                    Pithos.preventIESelection();
201
                }
202
            });
203
            publicPathText.setText(Window.Location.getHost() + file.getPublicUri());
204
            publicPathText.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");
205
            publicPathText.setReadOnly(true);
206
            publicPathPanel.add(publicPathText);
207

    
208
            publicSharingPanel.add(publicCheckPanel);
209
            publicSharingPanel.add(publicPathPanel);
210

    
211
            Scheduler.get().scheduleDeferred(new Command() {
212
                @Override
213
                public void execute() {
214
                    showLinkForPublicSharing();
215
                }
216
            });
217
        }
218
    }
219

    
220
    private void populatePrivateSharingPanel(VerticalPanel privateSharingPanel) {
221
        final HorizontalPanel privateCheckPanel = new HorizontalPanel();
222
        final VerticalPanel privatePermPanel = new VerticalPanel();
223
        final HorizontalPanel permButtons = new HorizontalPanel();
224

    
225
        privateCheckPanel.setSpacing(8);
226
        privatePermPanel.setVisible(isFilePrivatelyShared());
227
        permButtons.setSpacing(8);
228

    
229
        // Check box header
230
        final CheckBox privateCheckBox = new CheckBox();
231
        final Label privateCheckTitle = new  InlineHTML("<b>Private sharing</b>");
232
        final Label privateCheckInfo = new Label("Only people explicitly granted permission can access. Sign-in required.", true);
233

    
234
        privateCheckBox.setValue(isFilePrivatelyShared());
235
        privateCheckBox.addClickHandler(new ClickHandler() {
236
            @Override
237
            public void onClick(ClickEvent event) {
238
                if(isFilePrivatelyShared()) {
239
                    // ignore the click, set it always to "checked"
240
                    privateCheckBox.setValue(true);
241
                    // show permissions
242
                    privatePermPanel.setVisible(true);
243
                }
244
                else {
245
                    // This is the value *after* the click is applied :)
246
                    boolean isChecked = privateCheckBox.getValue();
247
                    privatePermPanel.setVisible(isChecked);
248
                }
249
            }
250
        });
251

    
252
        privateCheckPanel.add(privateCheckBox);
253
        privateCheckPanel.add(privateCheckTitle);
254
        privateCheckPanel.add(privateCheckInfo);
255

    
256
        // Permission list
257
        permList = new PermissionsList(app, privateSharingImages, file.getPermissions(), file.getOwnerID(), false, new Command() {
258
            @Override
259
            public void execute() {
260
                updateMetaDataForPrivateSharing();
261
            }
262
        });
263

    
264
        // Permission Add buttons
265
        Button addUser = new Button("Add User", new ClickHandler() {
266
            @Override
267
            public void onClick(ClickEvent event) {
268
                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);
269
                dlg.center();
270
                permList.updatePermissionTable();
271
            }
272
        });
273
        addUser.addStyleName("button");
274
        permButtons.add(addUser);
275
        permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);
276

    
277
        Button add = new Button("Add Group", new ClickHandler() {
278
            @Override
279
            public void onClick(ClickEvent event) {
280
                if (app.getAccount().getGroups().isEmpty()) {
281
                    new GroupCreateDialog(app, new Command() {
282

    
283
                        @Override
284
                        public void execute() {
285
                            if (app.getAccount().getGroups().isEmpty()) {
286
                                return;
287
                            }
288
                            PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
289
                            dlg.center();
290
                        }
291
                    }).center();
292
                }
293
                else {
294
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
295
                    dlg.center();
296
                }
297
            }
298
        });
299
        add.addStyleName("button");
300
        permButtons.add(add);
301
        permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);
302

    
303
        privatePermPanel.add(permList);
304
        privatePermPanel.add(permButtons);
305

    
306
        // Private Link
307
        privatePathPanel.setVisible(false);
308
        privatePathPanel.setWidth(Const.PERCENT_100);
309
        privatePathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
310
        privatePathPanel.add(new Label("Link"));
311
        privatePathPanel.setSpacing(8);
312
        privatePathPanel.addStyleName("pithos-TabPanelBottom");
313

    
314
        privatePathText.setWidth(Const.PERCENT_100);
315
        privatePathText.addClickHandler(new ClickHandler() {
316
            @Override
317
            public void onClick(ClickEvent event) {
318
                Pithos.enableIESelection();
319
                ((TextBox) event.getSource()).selectAll();
320
                Pithos.preventIESelection();
321
            }
322
        });
323
        privatePathText.setText(Window.Location.getHost() + file.getPublicUri());
324
        privatePathText.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");
325
        privatePathText.setWidth(Const.PERCENT_100);
326
        privatePathText.setReadOnly(true);
327
        privatePathPanel.add(privatePathText);
328

    
329
        Scheduler.get().scheduleDeferred(new Command() {
330
            @Override
331
            public void execute() {
332
                showLinkForPrivateSharing();
333
            }
334
        });
335

    
336
        privateSharingPanel.add(privateCheckPanel);
337
        privateSharingPanel.add(privatePermPanel);
338
        privateSharingPanel.add(privatePathPanel);
339
    }
340

    
341
    private Panel createMainPanel() {
342
        VerticalPanel panelAll = new VerticalPanel();
343
        VerticalPanel panelPublic = new VerticalPanel();
344
        VerticalPanel panelPrivate = new VerticalPanel();
345

    
346
        populatePrivateSharingPanel(panelPrivate);
347
        populatePublicSharingPanel(panelPublic);
348

    
349
        panelAll.add(panelPrivate);
350
        panelAll.add(panelPublic);
351

    
352
        return panelAll;
353
    }
354

    
355
    private boolean isFilePubliclyShared() {
356
        return file.isPublished();
357
    }
358

    
359
    private boolean isFilePrivatelyShared() {
360
        return file.isShared();
361
    }
362

    
363
    private void showLinkForPublicSharing() {
364
                if (isFilePubliclyShared()) {
365
                        UrlBuilder b = Window.Location.createUrlBuilder();
366
                        b.setPath(file.getPublicUri());
367
                        publicPathText.setText(b.buildString());
368
                publicPathPanel.setVisible(true);
369
                }
370
                else {
371
                        publicPathPanel.setVisible(false);
372
                }
373
    }
374

    
375
    private void showLinkForPrivateSharing() {
376
        if (isFilePrivatelyShared()) {
377
            UrlBuilder b = Window.Location.createUrlBuilder();
378
            b.setPath(app.getApiPath() + file.getOwnerID() + file.getUri());
379
            String href = Window.Location.getHref();
380
            boolean hasParameters = href.contains(Const.QUESTION_MARK);
381
            privatePathText.setText(href + (hasParameters ? Const.AMPERSAND : Const.QUESTION_MARK) + Const.GOTO_EQ + b.buildString());
382
            privatePathPanel.setVisible(true);
383
        }
384
        else {
385
            privatePathPanel.setVisible(false);
386
        }
387
    }
388

    
389
        protected void updateMetaDataForPublicSharing(String api, String owner, final String path, final Boolean published) {
390
        if (published != null) {
391
            PostRequest updateFile = new PostRequest(api, owner, path) {
392
                @Override
393
                public void onSuccess(Resource result) {
394
                        HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwnerID(), path, file) {
395

    
396
                                                @Override
397
                                                public void onSuccess(File _result) {
398
                                                        showLinkForPublicSharing();
399
                                                        if (!app.isMySharedSelected()) {
400
                                            app.updateFolder(file.getParent(), true, new Command() {
401
                                                                        
402
                                                                        @Override
403
                                                                        public void execute() {
404
                                                                                app.updateMySharedRoot();
405
                                                                        }
406
                                                                }, true);
407
                            }
408
                                                        else {
409
                                                                app.updateSharedFolder(file.getParent(), true);
410
                            }
411
                                                }
412

    
413
                                                @Override
414
                                                public void onError(Throwable t) {
415
                                                        app.setError(t);
416
                                    app.displayError("System error modifying file:" + t.getMessage());
417
                                                }
418

    
419
                                                @Override
420
                                                protected void onUnauthorized(Response response) {
421
                                                        app.sessionExpired();
422
                                                }
423
                                        };
424
                                        headFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
425
                                        Scheduler.get().scheduleDeferred(headFile);
426
                }
427

    
428
                @Override
429
                public void onError(Throwable t) {
430
                                        app.setError(t);
431
                    app.displayError("System error modifying file:" + t.getMessage());
432
                }
433

    
434
                                @Override
435
                                protected void onUnauthorized(Response response) {
436
                                        app.sessionExpired();
437
                                }
438
            };
439
            updateFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
440
            updateFile.setHeader(Const.X_OBJECT_PUBLIC, published.toString());
441
            Scheduler.get().scheduleDeferred(updateFile);
442
        }
443
        else if (!app.isMySharedSelected())
444
            app.updateFolder(file.getParent(), true, new Command() {
445
                                @Override
446
                                public void execute() {
447
                                        if (file.isSharedOrPublished()) {
448
                        app.updateMySharedRoot();
449
                    }
450
                                }
451
                        }, true);
452
        else
453
                app.updateSharedFolder(file.getParent(), true);
454
    }
455
    protected void updateMetaDataForPublicSharing(Boolean published) {
456
        updateMetaDataForPublicSharing(
457
            app.getApiPath(),
458
            app.getUserID(),
459
            file.getUri() + Const.QUESTION_MARK_UPDATE_EQ,
460
            published
461
        );
462
    }
463

    
464
    protected void updateMetaDataForPrivateSharing(String api, String owner, final String path, final Map<String, Boolean[]> newPermissions) {
465
        if (newPermissions != null) {
466
            PostRequest updateFile = new PostRequest(api, owner, path) {
467
                @Override
468
                public void onSuccess(Resource result) {
469
                    HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwnerID(), path, file) {
470

    
471
                        @Override
472
                        public void onSuccess(File _result) {
473
                            showLinkForPrivateSharing();
474
                            if (!app.isMySharedSelected())
475
                                app.updateFolder(file.getParent(), true, new Command() {
476

    
477
                                    @Override
478
                                    public void execute() {
479
                                        app.updateMySharedRoot();
480
                                    }
481
                                }, true);
482
                            else
483
                                app.updateSharedFolder(file.getParent(), true);
484
                        }
485

    
486
                        @Override
487
                        public void onError(Throwable t) {
488
                            app.setError(t);
489
                            app.displayError("System error modifying file:" + t.getMessage());
490
                        }
491

    
492
                        @Override
493
                        protected void onUnauthorized(Response response) {
494
                            app.sessionExpired();
495
                        }
496
                    };
497
                    headFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
498
                    Scheduler.get().scheduleDeferred(headFile);
499
                }
500

    
501
                @Override
502
                public void onError(Throwable t) {
503
                    app.setError(t);
504
                    app.displayError("System error modifying file:" + t.getMessage());
505
                }
506

    
507
                @Override
508
                protected void onUnauthorized(Response response) {
509
                    app.sessionExpired();
510
                }
511
            };
512
            updateFile.setHeader(Const.X_AUTH_TOKEN, app.getUserToken());
513

    
514
            String readPermHeader = Const.READ_EQ;
515
            String writePermHeader = Const.WRITE_EQ;
516
            for (String u : newPermissions.keySet()) {
517
                Boolean[] p = newPermissions.get(u);
518
                if (p[0] != null && p[0]) {
519
                    readPermHeader += u + Const.COMMA;
520
                }
521
                if (p[1] != null && p[1]) {
522
                    writePermHeader += u + Const.COMMA;
523
                }
524
            }
525
            if (readPermHeader.endsWith(Const.EQ)) {
526
                readPermHeader = "";
527
            }
528
            else if (readPermHeader.endsWith(Const.COMMA)) {
529
                readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
530
            }
531
            if (writePermHeader.endsWith(Const.EQ)) {
532
                writePermHeader = "";
533
            }
534
            else if (writePermHeader.endsWith(Const.COMMA)) {
535
                writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
536
            }
537
            String permHeader = readPermHeader +
538
                ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  Const.SEMI : "") + writePermHeader;
539
            if (permHeader.length() == 0) {
540
                permHeader=Const.TILDE;
541
            }
542
            else {
543
                permHeader = URL.encodePathSegment(permHeader);
544
            }
545
            updateFile.setHeader(Const.X_OBJECT_SHARING, permHeader);
546
            Scheduler.get().scheduleDeferred(updateFile);
547
        }
548
        else if (!app.isMySharedSelected()) {
549
            app.updateFolder(file.getParent(), true, new Command() {
550
                @Override
551
                public void execute() {
552
                    if (file.isSharedOrPublished())
553
                        app.updateMySharedRoot();
554
                }
555
            }, true);
556
        }
557
        else {
558
            app.updateSharedFolder(file.getParent(), true);
559
        }
560
    }
561
    protected void updateMetaDataForPrivateSharing() {
562
        updateMetaDataForPrivateSharing(
563
            app.getApiPath(),
564
            app.getUserID(),
565
            file.getUri() + Const.QUESTION_MARK_UPDATE_EQ,
566
            permList.getPermissions()
567
        );
568
    }
569
    @Override
570
        protected void onPreviewNativeEvent(NativePreviewEvent preview) {
571
            super.onPreviewNativeEvent(preview);
572

    
573
            NativeEvent evt = preview.getNativeEvent();
574
            if (evt.getType().equals(Const.EVENT_TYPE_KEYDOWN) &&
575
            evt.getKeyCode() == KeyCodes.KEY_ENTER) {
576

    
577
            closeDialog();
578
        }
579
        }
580

    
581
    @Override
582
    protected boolean accept() {
583
        return true;
584
    }
585
}