Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FilePropertiesDialog.java @ 3601b114

History | View | Annotate | Download (22 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.FileVersions;
39
import gr.grnet.pithos.web.client.foldertree.Resource;
40
import gr.grnet.pithos.web.client.foldertree.Version;
41
import gr.grnet.pithos.web.client.rest.GetRequest;
42
import gr.grnet.pithos.web.client.rest.PostRequest;
43
import gr.grnet.pithos.web.client.rest.PutRequest;
44
import gr.grnet.pithos.web.client.rest.RestException;
45

    
46
import java.util.HashMap;
47
import java.util.List;
48
import java.util.Map;
49

    
50
import com.google.gwt.core.client.GWT;
51
import com.google.gwt.core.client.Scheduler;
52
import com.google.gwt.event.dom.client.ClickEvent;
53
import com.google.gwt.event.dom.client.ClickHandler;
54
import com.google.gwt.http.client.Response;
55
import com.google.gwt.http.client.URL;
56
import com.google.gwt.i18n.client.DateTimeFormat;
57
import com.google.gwt.resources.client.ImageResource;
58
import com.google.gwt.user.client.Command;
59
import com.google.gwt.user.client.Window;
60
import com.google.gwt.user.client.ui.Anchor;
61
import com.google.gwt.user.client.ui.Button;
62
import com.google.gwt.user.client.ui.CheckBox;
63
import com.google.gwt.user.client.ui.DecoratedTabPanel;
64
import com.google.gwt.user.client.ui.FlexTable;
65
import com.google.gwt.user.client.ui.FocusPanel;
66
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
67
import com.google.gwt.user.client.ui.HorizontalPanel;
68
import com.google.gwt.user.client.ui.Image;
69
import com.google.gwt.user.client.ui.Label;
70
import com.google.gwt.user.client.ui.TextBox;
71
import com.google.gwt.user.client.ui.VerticalPanel;
72

    
73
/**
74
 * The 'File properties' dialog box implementation.
75
 *
76
 */
77
public class FilePropertiesDialog extends AbstractPropertiesDialog {
78

    
79
        protected PermissionsList permList;
80

    
81
        protected CheckBox readForAll;
82

    
83
        /**
84
         * An image bundle for this widgets images.
85
         */
86
        public interface Images extends MessagePanel.Images {
87

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

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

    
94
                @Source("gr/grnet/pithos/resources/editdelete.png")
95
                ImageResource delete();
96

    
97
                @Source("gr/grnet/pithos/resources/db_update.png")
98
                ImageResource restore();
99

    
100
                @Source("gr/grnet/pithos/resources/folder_inbox.png")
101
                ImageResource download();
102
        }
103

    
104
        /**
105
         * The widget that holds the name of the file.
106
         */
107
        private TextBox name = new TextBox();
108

    
109
        final File file;
110

    
111
    Images images = GWT.create(Images.class);
112

    
113
    FlexTable metaTable;
114
        /**
115
         * The widget's constructor.
116
         */
117
        public FilePropertiesDialog(Pithos _app, File _file) {
118
        super(_app);
119
        file = _file;
120

    
121
                Anchor close = new Anchor();
122
                close.addStyleName("close");
123
                close.addClickHandler(new ClickHandler() {
124
                        
125
                        @Override
126
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
127
                                hide();
128
                        }
129
                });
130
                // Set the dialog's caption.
131
                setText("File properties");
132
                setAnimationEnabled(true);
133
                setGlassEnabled(true);
134
                setStyleName("pithos-DialogBox");
135

    
136
                // Outer contains inner and buttons.
137
                final VerticalPanel outer = new VerticalPanel();
138
                outer.add(close);
139
                final FocusPanel focusPanel = new FocusPanel(outer);
140
                // Inner contains generalPanel and permPanel.
141
                inner = new DecoratedTabPanel();
142
                inner.setAnimationEnabled(true);
143
                inner.addStyleName("inner");
144
                inner.getDeckPanel().addStyleName("pithos-TabPanelBottom");
145

    
146

    
147
        inner.add(createGeneralPanel(), "General");
148

    
149
        inner.add(createSharingPanel(), "Sharing");
150

    
151
                fetchVersions();
152
                        
153
        inner.selectTab(0);
154

    
155
        outer.add(inner);
156

    
157
                // Create the 'OK' button, along with a listener that hides the dialog
158
                // when the button is clicked.
159
                final Button ok = new Button("OK", new ClickHandler() {
160
                        @Override
161
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
162
                                accept();
163
                                closeDialog();
164
                        }
165
                });
166
                ok.addStyleName("button");
167

    
168
        outer.add(ok);
169
        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
170

    
171
        focusPanel.setFocus(true);
172
        setWidget(outer);
173
        }
174

    
175
    protected void fetchVersions() {
176
            String path = file.getUri() + "?format=json&version=list";
177
            GetRequest<FileVersions> getVersions = new GetRequest<FileVersions>(FileVersions.class, app.getApiPath(), file.getOwner(), path) {
178

    
179
                        @Override
180
                        public void onSuccess(FileVersions _result) {
181
                        inner.add(createVersionPanel(_result.getVersions()), "Versions");
182
                        }
183

    
184
                        @Override
185
                        public void onError(Throwable t) {
186
                                GWT.log("", t);
187
                                app.setError(t);
188
                if (t instanceof RestException) {
189
                    app.displayError("Unable to fetch versions: " + ((RestException) t).getHttpStatusText());
190
                }
191
                else
192
                    app.displayError("System error unable to fetch versions: "+t.getMessage());
193
                        }
194

    
195
                        @Override
196
                        protected void onUnauthorized(@SuppressWarnings("unused") Response response) {
197
                                app.sessionExpired();
198
                        }
199
                };
200
                getVersions.setHeader("X-Auth-Token", app.getToken());
201
                Scheduler.get().scheduleDeferred(getVersions);
202
        }
203

    
204
        private VerticalPanel createGeneralPanel() {
205
        final VerticalPanel generalPanel = new VerticalPanel();
206
        final FlexTable generalTable = new FlexTable();
207
        generalTable.setText(0, 0, "Name");
208
        generalTable.setText(1, 0, "Folder");
209
        generalTable.setText(2, 0, "Owner");
210
        generalTable.setText(3, 0, "Last modified");
211

    
212
        name.setWidth("100%");
213
        name.setText(file.getName());
214
        generalTable.setWidget(0, 1, name);
215
        if(file.getParent() != null)
216
            generalTable.setText(1, 1, file.getParent().getName());
217
        else
218
            generalTable.setText(1, 1, "-");
219
        generalTable.setText(2, 1, file.getOwner());
220

    
221
        final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
222
        generalTable.setText(3, 1, file.getLastModified() != null ? formatter.format(file.getLastModified()) : "");
223

    
224
        generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
225
        generalTable.getFlexCellFormatter().setStyleName(1, 0, "props-labels");
226
        generalTable.getFlexCellFormatter().setStyleName(2, 0, "props-labels");
227
        generalTable.getFlexCellFormatter().setStyleName(3, 0, "props-labels");
228
        generalTable.getFlexCellFormatter().setStyleName(4, 0, "props-labels");
229
        generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");
230
        generalTable.getFlexCellFormatter().setStyleName(1, 1, "props-values");
231
        generalTable.getFlexCellFormatter().setStyleName(2, 1, "props-values");
232
        generalTable.getFlexCellFormatter().setStyleName(3, 1, "props-values");
233
        generalTable.setCellSpacing(4);
234

    
235
        generalPanel.add(generalTable);
236

    
237
        HorizontalPanel metaTitlePanel = new HorizontalPanel();
238
        metaTitlePanel.setSpacing(5);
239
        Label meta = new Label("Meta data");
240
        meta.addStyleName("pithos-metaTitle");
241
        metaTitlePanel.add(meta);
242
        
243
                Image plus = new Image("images/plus.png");
244
                plus.addStyleName("pithos-addMetaImg");
245
                metaTitlePanel.add(plus);
246
                
247
                generalPanel.add(metaTitlePanel);
248
                
249
                metaTable = new FlexTable();
250
                metaTable.setCellSpacing(0);
251
                metaTable.setHTML(0, 0, "Name");
252
                metaTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
253
                metaTable.setText(0, 1, "Value");
254
                metaTable.getFlexCellFormatter().setStyleName(0, 1, "props-labels");
255
                int rows = 1;
256
                for (String metaKey : file.getMeta().keySet()) {
257
                        addFormLine(metaTable, rows++, metaKey, file.getMeta().get(metaKey));
258
                }
259
                if (rows == 1) //If no meta add an empty line
260
                        addFormLine(metaTable, rows++, "", "");
261
                
262
                plus.addClickHandler(new ClickHandler() {
263
                        
264
                        @Override
265
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
266
                                addFormLine(metaTable, metaTable.getRowCount(), "", "");
267
                        }
268
                });
269

    
270
                generalPanel.add(metaTable);
271
        generalPanel.setSpacing(4);
272
        return generalPanel;
273
    }
274

    
275
        void addFormLine(final FlexTable table, int row, String _name, String _value) {
276
                TextBox nameBox = new TextBox();
277
                nameBox.setText(_name);
278
                nameBox.addStyleName("pithos-metaName");
279
                table.setWidget(row, 0, nameBox);
280
                table.getFlexCellFormatter().setStyleName(1, 0, "props-values");
281

    
282
                TextBox valueBox = new TextBox();
283
                valueBox.setText(_value);
284
                valueBox.addStyleName("pithos-metaValue");
285
                table.setWidget(row, 1, valueBox);
286
                table.getFlexCellFormatter().setStyleName(1, 1, "props-values");
287
                
288
                Image delete = new Image("images/delete.png");
289
                delete.addStyleName("pithos-metaDeleteImg");
290
                delete.addClickHandler(new ClickHandler() {
291
                        
292
                        @Override
293
                        public void onClick(ClickEvent event) {
294
                                int rowIndex = table.getCellForEvent(event).getRowIndex();
295
                                table.removeRow(rowIndex);
296
                        }
297
                });
298
                table.setWidget(row, 2, delete);
299
        }
300

    
301
    private VerticalPanel createSharingPanel() {
302
        VerticalPanel permPanel = new VerticalPanel();
303

    
304
        permList = new PermissionsList(images, file.getPermissions(), file.getOwner(), file.getInheritedPermissionsFrom() != null);
305
        permPanel.add(permList);
306

    
307
        if (file.getInheritedPermissionsFrom() == null) {
308
            HorizontalPanel permButtons = new HorizontalPanel();
309
            Button add = new Button("Add Group", new ClickHandler() {
310
                @Override
311
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
312
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
313
                    dlg.center();
314
                    permList.updatePermissionTable();
315
                }
316
            });
317
            add.addStyleName("button");
318
            permButtons.add(add);
319
            permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);
320

    
321
            final Button addUser = new Button("Add User", new ClickHandler() {
322
                @Override
323
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
324
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);
325
                    dlg.center();
326
                    permList.updatePermissionTable();
327
                }
328
            });
329
            addUser.addStyleName("button");
330
            permButtons.add(addUser);
331
            permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);
332

    
333
            permButtons.setSpacing(8);
334
            permButtons.addStyleName("pithos-TabPanelBottom");
335
            permPanel.add(permButtons);
336
        }
337

    
338
        final Label readForAllNote = new Label("When this option is enabled, the file will be readable" +
339
                    " by everyone. By checking this option, you are certifying that you have the right to " +
340
                    "distribute this file and that it does not violate the Terms of Use.", true);
341
        readForAllNote.setVisible(false);
342
        readForAllNote.setStylePrimaryName("pithos-readForAllNote");
343

    
344
        readForAll = new CheckBox();
345
        readForAll.setValue(file.isPublished());
346
        readForAll.addClickHandler(new ClickHandler() {
347
            @Override
348
            public void onClick(@SuppressWarnings("unused") ClickEvent event) {
349
                readForAllNote.setVisible(readForAll.getValue());
350
            }
351
        });
352

    
353
        // Only show the read for all permission if the user is the owner.
354
        if (file.getOwner().equals(app.getUsername())) {
355
            final HorizontalPanel permForAll = new HorizontalPanel();
356
            permForAll.add(new Label("Public"));
357
            permForAll.add(readForAll);
358
            permForAll.setSpacing(8);
359
            permForAll.addStyleName("pithos-TabPanelBottom");
360
            permForAll.add(readForAllNote);
361
            permPanel.add(permForAll);
362
        }
363

    
364
        if (file.isPublished()) {
365
            final HorizontalPanel pathPanel = new HorizontalPanel();
366
            pathPanel.setWidth("100%");
367
            pathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
368
            pathPanel.add(new Label("Link"));
369
            pathPanel.setSpacing(8);
370
            pathPanel.addStyleName("pithos-TabPanelBottom");
371

    
372
            TextBox path = new TextBox();
373
            path.setWidth("100%");
374
            path.addClickHandler(new ClickHandler() {
375
                @Override
376
                public void onClick(ClickEvent event) {
377
                    Pithos.enableIESelection();
378
                    ((TextBox) event.getSource()).selectAll();
379
                    Pithos.preventIESelection();
380
                }
381
            });
382
            path.setText(Window.Location.getHost() + file.getPublicUri());
383
            path.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");
384
            path.setWidth("100%");
385
            path.setReadOnly(true);
386
            pathPanel.add(path);
387
            permPanel.add(pathPanel);
388
        }
389

    
390
        return permPanel;
391
    }
392

    
393
    VerticalPanel createVersionPanel(List<Version> versions) {
394
        VerticalPanel versionPanel = new VerticalPanel();
395
        VersionsList verList = new VersionsList(app, this, images, file, versions);
396
        versionPanel.add(verList);
397
        return versionPanel;
398
    }
399

    
400
        /**
401
         * Accepts any change and updates the file
402
         *
403
         */
404
        @Override
405
        protected void accept() {
406
                String newFilename = null;
407

    
408
                final Map<String, Boolean[]> perms = (permList.hasChanges() ? permList.getPermissions() : null);
409

    
410
                if (!name.getText().trim().equals(file.getName())) {
411
                        newFilename = name.getText().trim();
412
                }
413

    
414
                //only update the read for all perm if the user is the owner
415
        Boolean published = null;
416
                if (readForAll.getValue() != file.isPublished())
417
                        if (file.getOwner().equals(app.getUsername()))
418
                published = readForAll.getValue();
419
        final Boolean finalPublished = published;
420

    
421
        final Map<String, String> newMeta = new HashMap<String, String>();
422
        for (int row = 1; row < metaTable.getRowCount(); row++) {
423
                String key = ((TextBox) metaTable.getWidget(row, 0)).getText().trim();
424
                String value = ((TextBox) metaTable.getWidget(row, 1)).getText().trim();
425
                if (key.length() > 0 && value.length() > 0)
426
                        newMeta.put(key, value);
427
        }
428

    
429
        if (newFilename != null) {
430
            final String path = file.getParent().getUri() + "/" + newFilename;
431
            PutRequest updateFile = new PutRequest(app.getApiPath(), app.getUsername(), path) {
432
                @Override
433
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
434
                    updateMetaData(app.getApiPath(), file.getOwner(), path + "?update=", newMeta, finalPublished, perms);
435
                }
436

    
437
                @Override
438
                public void onError(Throwable t) {
439
                    GWT.log("", t);
440
                                        app.setError(t);
441
                    app.displayError("System error modifying file:" + t.getMessage());
442
                }
443

    
444
                                @Override
445
                                protected void onUnauthorized(@SuppressWarnings("unused") Response response) {
446
                                        app.sessionExpired();
447
                                }
448
            };
449
            updateFile.setHeader("X-Auth-Token", app.getToken());
450
            updateFile.setHeader("X-Move-From", URL.encodePathSegment(file.getUri()));
451
            updateFile.setHeader("Content-Type", file.getContentType());
452
            for (String key : file.getMeta().keySet())
453
                updateFile.setHeader("X-Object-Meta-" + URL.encodePathSegment(key.trim()), URL.encodePathSegment(newMeta.get(key)));
454
            if (file.isPublished())
455
                updateFile.setHeader("X-Object-Public", "true");
456
            String readPermHeader = "read=";
457
            String writePermHeader = "write=";
458
            for (String u : file.getPermissions().keySet()) {
459
                Boolean[] p = file.getPermissions().get(u);
460
                if (p[0] != null && p[0])
461
                    readPermHeader += u + ",";
462
                if (p[1] != null && p[1])
463
                    writePermHeader += u + ",";
464
            }
465
            if (readPermHeader.endsWith("="))
466
                readPermHeader = "";
467
            else if (readPermHeader.endsWith(","))
468
                readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
469
            if (writePermHeader.endsWith("="))
470
                writePermHeader = "";
471
            else if (writePermHeader.endsWith(","))
472
                writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
473
            String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;
474
            if (permHeader.length() == 0)
475
                permHeader="~";
476
            else
477
                    permHeader = URL.encodePathSegment(permHeader);
478
            updateFile.setHeader("X-Object-Sharing", permHeader);
479

    
480
            Scheduler.get().scheduleDeferred(updateFile);
481
        }
482
        else
483
            updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", newMeta, finalPublished, perms);
484
        }
485

    
486
        protected void updateMetaData(String api, String owner, String path, Map<String, String> newMeta, final Boolean published, final Map<String, Boolean[]> newPermissions) {
487
        if (newMeta != null || published != null || newPermissions != null) {
488
            PostRequest updateFile = new PostRequest(api, owner, path) {
489
                @Override
490
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
491
                    app.updateFolder(file.getParent(), true, new Command() {
492
                                                
493
                                                @Override
494
                                                public void execute() {
495
                                                        app.updateMySharedRoot();
496
                                                }
497
                                        });
498
                }
499

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

    
507
                                @Override
508
                                protected void onUnauthorized(@SuppressWarnings("unused") Response response) {
509
                                        app.sessionExpired();
510
                                }
511
            };
512
            updateFile.setHeader("X-Auth-Token", app.getToken());
513
            
514
            if (newMeta != null) {
515
                    for (String t : file.getMeta().keySet()) {
516
                                updateFile.setHeader("X-Object-Meta-" + URL.encodePathSegment(t.trim()), "~");
517
                    }
518
                    
519
                    for (String key : newMeta.keySet())
520
                        updateFile.setHeader("X-Object-Meta-" + URL.encodePathSegment(key.trim()), URL.encodePathSegment(newMeta.get(key)));
521
            }
522
            
523
            if (published != null)
524
                updateFile.setHeader("X-Object-Public", published.toString());
525
            if (newPermissions != null) {
526
                String readPermHeader = "read=";
527
                String writePermHeader = "write=";
528
                for (String u : newPermissions.keySet()) {
529
                    Boolean[] p = newPermissions.get(u);
530
                    if (p[0] != null && p[0])
531
                        readPermHeader += u + ",";
532
                    if (p[1] != null && p[1])
533
                        writePermHeader += u + ",";
534
                }
535
                if (readPermHeader.endsWith("="))
536
                    readPermHeader = "";
537
                else if (readPermHeader.endsWith(","))
538
                    readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
539
                if (writePermHeader.endsWith("="))
540
                    writePermHeader = "";
541
                else if (writePermHeader.endsWith(","))
542
                    writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
543
                String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;
544
                if (permHeader.length() == 0)
545
                    permHeader="~";
546
                else
547
                        permHeader = URL.encodePathSegment(permHeader);
548
                updateFile.setHeader("X-Object-Sharing", permHeader);
549
            }
550
            Scheduler.get().scheduleDeferred(updateFile);
551
        }
552
        else
553
            app.updateFolder(file.getParent(), true, new Command() {
554
                                
555
                                @Override
556
                                public void execute() {
557
                                        if (file.isShared())
558
                                                app.updateMySharedRoot();
559
                                }
560
                        });
561
    }
562
}