Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (21.5 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(Const.TXT_SHARE_FILE);
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(Const.TXT_PUBLIC_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

    
276
        final boolean haveGroups = app.getAccount().getGroups().size() > 0;
277

    
278
        if(haveGroups) {
279
            Button addGroup = new Button("Add Group", new ClickHandler() {
280
                @Override
281
                public void onClick(ClickEvent event) {
282
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
283
                    dlg.center();
284
                    permList.updatePermissionTable();
285
                }
286
            });
287
            addGroup.addStyleName("button");
288

    
289
            permButtons.add(addGroup);
290
            permButtons.setCellHorizontalAlignment(addGroup, HasHorizontalAlignment.ALIGN_CENTER);
291
        }
292

    
293
        final Button addEverybody = new Button("Add everybody", new ClickHandler() {
294
            @Override
295
            public void onClick(ClickEvent event) {
296
                Pithos.LOG("Adding to Everybody");
297
                Pithos.LOG("");
298
                permList.addPermission("*", true, false);
299
                permList.updatePermissionTable();
300
            }
301
        });
302
        addEverybody.addStyleName("button");
303
        permButtons.add(addEverybody);
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(Const.TXT_PRIVATE_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(new InlineHTML("<hr/>"));
353
        panelAll.add(panelPublic);
354

    
355
        return panelAll;
356
    }
357

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
580
            closeDialog();
581
        }
582
        }
583

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