Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FilePropertiesDialog.java @ 7228fda0

History | View | Annotate | Download (19.3 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
import gr.grnet.pithos.web.client.tagtree.Tag;
46

    
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.i18n.client.DateTimeFormat;
56
import com.google.gwt.resources.client.ImageResource;
57
import com.google.gwt.user.client.Window;
58
import com.google.gwt.user.client.ui.Anchor;
59
import com.google.gwt.user.client.ui.Button;
60
import com.google.gwt.user.client.ui.CheckBox;
61
import com.google.gwt.user.client.ui.DecoratedTabPanel;
62
import com.google.gwt.user.client.ui.DisclosurePanel;
63
import com.google.gwt.user.client.ui.FlexTable;
64
import com.google.gwt.user.client.ui.FlowPanel;
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.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
        /**
113
         * The widget's constructor.
114
         */
115
        public FilePropertiesDialog(Pithos _app, File _file) {
116
        super(_app);
117
        file = _file;
118

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

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

    
144

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

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

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

    
153
        outer.add(inner);
154

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

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

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

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

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

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

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

    
201
        private VerticalPanel createGeneralPanel() {
202
        final VerticalPanel generalPanel = new VerticalPanel();
203
        final FlexTable generalTable = new FlexTable();
204
        generalTable.setText(0, 0, "Name");
205
        generalTable.setText(1, 0, "Folder");
206
        generalTable.setText(2, 0, "Owner");
207
        generalTable.setText(3, 0, "Last modified");
208
        generalTable.setText(4, 0, "Tags");
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
                StringBuffer tagsBuffer = new StringBuffer();
223
        for (String t : file.getTags())
224
                        tagsBuffer.append(t).append(", ");
225
                if (tagsBuffer.length() > 1)
226
                        tagsBuffer.delete(tagsBuffer.length() - 2, tagsBuffer.length() - 1);
227
                initialTagText = tagsBuffer.toString();
228
                tags.setWidth("100%");
229
                tags.setText(initialTagText);
230
                generalTable.setWidget(4, 1, tags);
231

    
232
        generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
233
        generalTable.getFlexCellFormatter().setStyleName(1, 0, "props-labels");
234
        generalTable.getFlexCellFormatter().setStyleName(2, 0, "props-labels");
235
        generalTable.getFlexCellFormatter().setStyleName(3, 0, "props-labels");
236
        generalTable.getFlexCellFormatter().setStyleName(4, 0, "props-labels");
237
        generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");
238
        generalTable.getFlexCellFormatter().setStyleName(1, 1, "props-values");
239
        generalTable.getFlexCellFormatter().setStyleName(2, 1, "props-values");
240
        generalTable.getFlexCellFormatter().setStyleName(3, 1, "props-values");
241
        generalTable.getFlexCellFormatter().setStyleName(4, 1, "props-values");
242
        generalTable.setCellSpacing(4);
243

    
244
        generalPanel.add(generalTable);
245

    
246
        DisclosurePanel allTags = new DisclosurePanel("All tags");
247
        allTagsContent = new FlowPanel();
248
        allTagsContent.setWidth("100%");
249
        for (Tag t : app.getAllTags()) {
250
            final Anchor tagAnchor = new Anchor(t.getName(), false);
251
            tagAnchor.addStyleName("pithos-tag");
252
            allTagsContent.add(tagAnchor);
253
            Label separator = new Label(", ");
254
            separator.addStyleName("pithos-tag");
255
            allTagsContent.add(separator);
256
            tagAnchor.addClickHandler(new ClickHandler() {
257

    
258
                @Override
259
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
260
                    String existing = tags.getText().trim();
261
                    if (MULTIPLE_VALUES_TEXT.equals(existing))
262
                        existing = "";
263
                    String newTag = tagAnchor.getText().trim();
264
                    // insert the new tag only if it is not in the list
265
                    // already
266
                    if (existing.indexOf(newTag) == -1)
267
                        tags.setText(existing + (existing.length() > 0 ? ", " : "") + newTag);
268
                }
269
            });
270
        }
271
        allTags.setContent(allTagsContent);
272
        generalPanel.add(allTags);
273
        generalPanel.setSpacing(4);
274
        return generalPanel;
275
    }
276

    
277
    private VerticalPanel createSharingPanel() {
278
        VerticalPanel permPanel = new VerticalPanel();
279

    
280
        permList = new PermissionsList(images, file.getPermissions(), file.getOwner(), file.getInheritedPermissionsFrom() != null);
281
        permPanel.add(permList);
282

    
283
        if (file.getInheritedPermissionsFrom() == null) {
284
            HorizontalPanel permButtons = new HorizontalPanel();
285
            Button add = new Button("Add Group", new ClickHandler() {
286
                @Override
287
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
288
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
289
                    dlg.center();
290
                    permList.updatePermissionTable();
291
                }
292
            });
293
            add.addStyleName("button");
294
            permButtons.add(add);
295
            permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);
296

    
297
            final Button addUser = new Button("Add User", new ClickHandler() {
298
                @Override
299
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
300
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);
301
                    dlg.center();
302
                    permList.updatePermissionTable();
303
                }
304
            });
305
            addUser.addStyleName("button");
306
            permButtons.add(addUser);
307
            permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);
308

    
309
            permButtons.setSpacing(8);
310
            permButtons.addStyleName("pithos-TabPanelBottom");
311
            permPanel.add(permButtons);
312
        }
313

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

    
320
        readForAll = new CheckBox();
321
        readForAll.setValue(file.isPublished());
322
        readForAll.addClickHandler(new ClickHandler() {
323
            @Override
324
            public void onClick(@SuppressWarnings("unused") ClickEvent event) {
325
                readForAllNote.setVisible(readForAll.getValue());
326
            }
327
        });
328

    
329
        // Only show the read for all permission if the user is the owner.
330
        if (file.getOwner().equals(app.getUsername())) {
331
            final HorizontalPanel permForAll = new HorizontalPanel();
332
            permForAll.add(new Label("Public"));
333
            permForAll.add(readForAll);
334
            permForAll.setSpacing(8);
335
            permForAll.addStyleName("pithos-TabPanelBottom");
336
            permForAll.add(readForAllNote);
337
            permPanel.add(permForAll);
338
        }
339

    
340
        if (file.isPublished()) {
341
            final HorizontalPanel pathPanel = new HorizontalPanel();
342
            pathPanel.setWidth("100%");
343
            pathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);
344
            pathPanel.add(new Label("Link"));
345
            pathPanel.setSpacing(8);
346
            pathPanel.addStyleName("pithos-TabPanelBottom");
347

    
348
            TextBox path = new TextBox();
349
            path.setWidth("100%");
350
            path.addClickHandler(new ClickHandler() {
351
                @Override
352
                public void onClick(ClickEvent event) {
353
                    Pithos.enableIESelection();
354
                    ((TextBox) event.getSource()).selectAll();
355
                    Pithos.preventIESelection();
356
                }
357
            });
358
            path.setText(Window.Location.getHost() + file.getPublicUri());
359
            path.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");
360
            path.setWidth("100%");
361
            path.setReadOnly(true);
362
            pathPanel.add(path);
363
            permPanel.add(pathPanel);
364
        }
365

    
366
        return permPanel;
367
    }
368

    
369
    VerticalPanel createVersionPanel(List<Version> versions) {
370
        VerticalPanel versionPanel = new VerticalPanel();
371
        VersionsList verList = new VersionsList(app, this, images, file, versions);
372
        versionPanel.add(verList);
373
        return versionPanel;
374
    }
375

    
376
        /**
377
         * Accepts any change and updates the file
378
         *
379
         */
380
        @Override
381
        protected void accept() {
382
                String newFilename = null;
383

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

    
386
                if (!name.getText().trim().equals(file.getName())) {
387
                        newFilename = name.getText().trim();
388
                }
389

    
390
                //only update the read for all perm if the user is the owner
391
        Boolean published = null;
392
                if (readForAll.getValue() != file.isPublished())
393
                        if (file.getOwner().equals(app.getUsername()))
394
                published = readForAll.getValue();
395
        final Boolean finalPublished = published;
396

    
397
        String[] tagset = null;
398
                if (!tags.getText().equals(initialTagText))
399
                        tagset = tags.getText().trim().split(",");
400
        final String[] newTags = tagset;
401

    
402
        if (newFilename != null) {
403
            final String path = file.getParent().getUri() + "/" + newFilename;
404
            PutRequest updateFile = new PutRequest(app.getApiPath(), app.getUsername(), path) {
405
                @Override
406
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
407
                    updateMetaData(app.getApiPath(), file.getOwner(), path + "?update=", newTags, finalPublished, perms);
408
                }
409

    
410
                @Override
411
                public void onError(Throwable t) {
412
                    GWT.log("", t);
413
                    app.displayError("System error modifying file:" + t.getMessage());
414
                }
415

    
416
                                @Override
417
                                protected void onUnauthorized(Response response) {
418
                                        app.sessionExpired();
419
                                }
420
            };
421
            updateFile.setHeader("X-Auth-Token", app.getToken());
422
            updateFile.setHeader("X-Move-From", file.getUri());
423
            updateFile.setHeader("Content-Type", file.getContentType());
424
            Scheduler.get().scheduleDeferred(updateFile);
425
        }
426
        else
427
            updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", newTags, finalPublished, perms);
428
        }
429

    
430
        protected void updateMetaData(String api, String owner, String path, String[] newTags, Boolean published, Map<String, Boolean[]> newPermissions) {
431
        if (newTags != null || published != null || newPermissions != null) {
432
            PostRequest updateFile = new PostRequest(api, owner, path) {
433
                @Override
434
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
435
                    app.updateFolder(file.getParent(), true, null);
436
                }
437

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

    
444
                                @Override
445
                                protected void onUnauthorized(Response response) {
446
                                        app.sessionExpired();
447
                                }
448
            };
449
            updateFile.setHeader("X-Auth-Token", app.getToken());
450
            if (newTags != null)
451
                for (String t : newTags)
452
                        if (t.length() > 0)
453
                                updateFile.setHeader("X-Object-Meta-" + t.trim(), "true");
454
                for (String t : file.getTags())
455
                            updateFile.setHeader("X-Object-Meta-" + t.trim(), "~");
456
            if (published != null)
457
                updateFile.setHeader("X-Object-Public", published.toString());
458
            if (newPermissions != null) {
459
                String readPermHeader = "read=";
460
                String writePermHeader = "write=";
461
                for (String u : newPermissions.keySet()) {
462
                    Boolean[] p = newPermissions.get(u);
463
                    if (p[0] != null && p[0])
464
                        readPermHeader += u + ",";
465
                    if (p[1] != null && p[1])
466
                        writePermHeader += u + ",";
467
                }
468
                if (readPermHeader.endsWith("="))
469
                    readPermHeader = "";
470
                else if (readPermHeader.endsWith(","))
471
                    readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
472
                if (writePermHeader.endsWith("="))
473
                    writePermHeader = "";
474
                else if (writePermHeader.endsWith(","))
475
                    writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
476
                String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;
477
                if (permHeader.length() == 0)
478
                    permHeader="~";
479
                updateFile.setHeader("X-Object-Sharing", permHeader);
480
            }
481
            Scheduler.get().scheduleDeferred(updateFile);
482
        }
483
        else
484
            app.updateFolder(file.getParent(), true, null);
485
    }
486
}