Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (21.6 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
        this.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
                            permList.updatePermissionTable();
291
                        }
292
                    }).center();
293
                }
294
                else {
295
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
296
                    dlg.center();
297
                    permList.updatePermissionTable();
298
                }
299
            }
300
        });
301
        add.addStyleName("button");
302
        permButtons.add(add);
303
        permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);
304

    
305
        privatePermPanel.add(permList);
306
        privatePermPanel.add(permButtons);
307

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

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

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

    
338
        privateSharingPanel.add(privateCheckPanel);
339
        privateSharingPanel.add(privatePermPanel);
340
        privateSharingPanel.add(privatePathPanel);
341
    }
342

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

    
348
        populatePrivateSharingPanel(panelPrivate);
349
        populatePublicSharingPanel(panelPublic);
350

    
351
        panelAll.add(panelPrivate);
352
        panelAll.add(panelPublic);
353

    
354
        return panelAll;
355
    }
356

    
357
    private boolean isFilePubliclyShared() {
358
        return file.isPublished();
359
    }
360

    
361
    private boolean isFilePrivatelyShared() {
362
        return file.isShared();
363
    }
364

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
579
            closeDialog();
580
        }
581
        }
582

    
583
    @Override
584
    protected boolean accept() {
585
        return true;
586
    }
587
}