Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FilePropertiesDialog.java @ 904447e4

History | View | Annotate | Download (20.1 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.Window;
59
import com.google.gwt.user.client.ui.Anchor;
60
import com.google.gwt.user.client.ui.Button;
61
import com.google.gwt.user.client.ui.CheckBox;
62
import com.google.gwt.user.client.ui.DecoratedTabPanel;
63
import com.google.gwt.user.client.ui.FlexTable;
64
import com.google.gwt.user.client.ui.FocusPanel;
65
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
66
import com.google.gwt.user.client.ui.HorizontalPanel;
67
import com.google.gwt.user.client.ui.Image;
68
import com.google.gwt.user.client.ui.Label;
69
import com.google.gwt.user.client.ui.TextBox;
70
import com.google.gwt.user.client.ui.VerticalPanel;
71

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

    
78
        protected PermissionsList permList;
79

    
80
        protected CheckBox readForAll;
81

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

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

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

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

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

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

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

    
108
        final File file;
109

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

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

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

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

    
145

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

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

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

    
154
        outer.add(inner);
155

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

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

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

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

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

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

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

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

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

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

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

    
233
        generalPanel.add(generalTable);
234

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

    
268
                generalPanel.add(metaTable);
269
        generalPanel.setSpacing(4);
270
        return generalPanel;
271
    }
272

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

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

    
299
    private VerticalPanel createSharingPanel() {
300
        VerticalPanel permPanel = new VerticalPanel();
301

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

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

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

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

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

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

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

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

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

    
388
        return permPanel;
389
    }
390

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

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

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

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

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

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

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

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

    
441
                                @Override
442
                                protected void onUnauthorized(@SuppressWarnings("unused") Response response) {
443
                                        app.sessionExpired();
444
                                }
445
            };
446
            updateFile.setHeader("X-Auth-Token", app.getToken());
447
            updateFile.setHeader("X-Move-From", URL.encodePathSegment(file.getUri()));
448
            updateFile.setHeader("Content-Type", file.getContentType());
449
            Scheduler.get().scheduleDeferred(updateFile);
450
        }
451
        else
452
            updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", newMeta, finalPublished, perms);
453
        }
454

    
455
        protected void updateMetaData(String api, String owner, String path, Map<String, String> newMeta, Boolean published, Map<String, Boolean[]> newPermissions) {
456
        if (newMeta != null || published != null || newPermissions != null) {
457
            PostRequest updateFile = new PostRequest(api, owner, path) {
458
                @Override
459
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
460
                    app.updateFolder(file.getParent(), true, null);
461
                }
462

    
463
                @Override
464
                public void onError(Throwable t) {
465
                    GWT.log("", t);
466
                    app.displayError("System error modifying file:" + t.getMessage());
467
                }
468

    
469
                                @Override
470
                                protected void onUnauthorized(@SuppressWarnings("unused") Response response) {
471
                                        app.sessionExpired();
472
                                }
473
            };
474
            updateFile.setHeader("X-Auth-Token", app.getToken());
475
            
476
            if (newMeta != null) {
477
                    for (String t : file.getMeta().keySet()) {
478
                                updateFile.setHeader("X-Object-Meta-" + URL.encodePathSegment(t.trim()), "~");
479
                    }
480
                    
481
                    for (String key : newMeta.keySet())
482
                        updateFile.setHeader("X-Object-Meta-" + URL.encodePathSegment(key.trim()), URL.encodePathSegment(newMeta.get(key)));
483
            }
484
            
485
            if (published != null)
486
                updateFile.setHeader("X-Object-Public", published.toString());
487
            if (newPermissions != null) {
488
                String readPermHeader = "read=";
489
                String writePermHeader = "write=";
490
                for (String u : newPermissions.keySet()) {
491
                    Boolean[] p = newPermissions.get(u);
492
                    if (p[0] != null && p[0])
493
                        readPermHeader += u + ",";
494
                    if (p[1] != null && p[1])
495
                        writePermHeader += u + ",";
496
                }
497
                if (readPermHeader.endsWith("="))
498
                    readPermHeader = "";
499
                else if (readPermHeader.endsWith(","))
500
                    readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
501
                if (writePermHeader.endsWith("="))
502
                    writePermHeader = "";
503
                else if (writePermHeader.endsWith(","))
504
                    writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
505
                String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;
506
                if (permHeader.length() == 0)
507
                    permHeader="~";
508
                else
509
                        permHeader = URL.encodePathSegment(permHeader);
510
                updateFile.setHeader("X-Object-Sharing", permHeader);
511
            }
512
            Scheduler.get().scheduleDeferred(updateFile);
513
        }
514
        else
515
            app.updateFolder(file.getParent(), true, null);
516
    }
517
}