Statistics
| Branch: | Tag: | Revision:

root / src / gr / grnet / pithos / web / client / FolderPropertiesDialog.java @ 969a4d94

History | View | Annotate | Download (17.8 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 com.google.gwt.core.client.Scheduler;
38
import com.google.gwt.event.dom.client.KeyDownEvent;
39
import com.google.gwt.user.client.Command;
40
import gr.grnet.pithos.web.client.foldertree.File;
41
import gr.grnet.pithos.web.client.foldertree.Folder;
42
import gr.grnet.pithos.web.client.foldertree.Resource;
43
import gr.grnet.pithos.web.client.rest.PostRequest;
44
import gr.grnet.pithos.web.client.rest.PutRequest;
45
import gr.grnet.pithos.web.client.rest.RestException;
46

    
47
import com.google.gwt.core.client.GWT;
48
import com.google.gwt.dom.client.NativeEvent;
49
import com.google.gwt.event.dom.client.ClickEvent;
50
import com.google.gwt.event.dom.client.ClickHandler;
51
import com.google.gwt.event.dom.client.KeyCodes;
52
import com.google.gwt.http.client.Response;
53
import com.google.gwt.i18n.client.DateTimeFormat;
54
import com.google.gwt.user.client.Event.NativePreviewEvent;
55
import com.google.gwt.user.client.ui.Anchor;
56
import com.google.gwt.user.client.ui.Button;
57
import com.google.gwt.user.client.ui.DecoratedTabPanel;
58
import com.google.gwt.user.client.ui.DialogBox;
59
import com.google.gwt.user.client.ui.FlexTable;
60
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
61
import com.google.gwt.user.client.ui.HorizontalPanel;
62
import com.google.gwt.user.client.ui.TabPanel;
63
import com.google.gwt.user.client.ui.TextBox;
64
import com.google.gwt.user.client.ui.VerticalPanel;
65
import java.util.Iterator;
66
import java.util.Map;
67

    
68
/**
69
 * The 'Folder properties' dialog box implementation.
70
 */
71
public class FolderPropertiesDialog extends DialogBox {
72

    
73
    protected Pithos app;
74

    
75
        /**
76
         * The widget that holds the folderName of the folder.
77
         */
78
        private TextBox folderName = new TextBox();
79

    
80
        /**
81
         * A flag that denotes whether the dialog will be used to create or modify a
82
         * folder.
83
         */
84
        private final boolean create;
85

    
86
        protected PermissionsList permList;
87

    
88
        final Folder folder;
89

    
90
        final TabPanel inner;
91

    
92
        /**
93
         * The widget's constructor.
94
         */
95
        public FolderPropertiesDialog(final Pithos app, boolean _create,  Folder selected) {
96
        this.app = app;
97
                Anchor close = new Anchor();
98
                close.addStyleName("close");
99
                close.addClickHandler(new ClickHandler() {
100
                        
101
                        @Override
102
                        public void onClick(ClickEvent event) {
103
                                hide();
104
                        }
105
                });
106

    
107
                setAnimationEnabled(true);
108
                setGlassEnabled(true);
109
                setStyleName("pithos-DialogBox");
110

    
111
                // Enable IE selection for the dialog (must disable it upon closing it)
112
                Pithos.enableIESelection();
113

    
114
                create = _create;
115
                
116
                folder = selected;
117

    
118
                // Use this opportunity to set the dialog's caption.
119
                if (create)
120
                        setText("Create folder");
121
                else
122
                        setText("Folder properties");
123

    
124
                // Outer contains inner and buttons
125
                VerticalPanel outer = new VerticalPanel();
126
                outer.add(close);
127
                // Inner contains generalPanel and permPanel
128
                inner = new DecoratedTabPanel();
129
                inner.setAnimationEnabled(true);
130
                inner.addStyleName("inner");
131
                inner.getDeckPanel().addStyleName("pithos-TabPanelBottom");
132

    
133
                VerticalPanel generalPanel = new VerticalPanel();
134
        FlexTable generalTable = new FlexTable();
135
        generalTable.setText(0, 0, "Name");
136
        generalTable.setText(1, 0, "Parent");
137
        generalTable.setText(2, 0, "Creator");
138
        generalTable.setText(3, 0, "Last modified");
139
        folderName.setText(create ? "" : folder.getName());
140
        folderName.setReadOnly(folder.isContainer() && !create);
141
        generalTable.setWidget(0, 1, folderName);
142

    
143
        if (create)
144
            generalTable.setText(1, 1, folder.getName());
145
        else
146
            generalTable.setText(1, 1, folder.getPrefix());
147
        generalTable.setText(2, 1, "");
148
        DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
149
        if(folder.getLastModified() != null)
150
            generalTable.setText(3, 1, formatter.format(folder.getLastModified()));
151
        generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
152
        generalTable.getFlexCellFormatter().setStyleName(1, 0, "props-labels");
153
        generalTable.getFlexCellFormatter().setStyleName(2, 0, "props-labels");
154
        generalTable.getFlexCellFormatter().setStyleName(3, 0, "props-labels");
155
        generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");
156
        generalTable.getFlexCellFormatter().setStyleName(1, 1, "props-values");
157
        generalTable.getFlexCellFormatter().setStyleName(2, 1, "props-values");
158
        generalTable.getFlexCellFormatter().setStyleName(3, 1, "props-values");
159
        generalTable.setCellSpacing(4);
160
        generalPanel.add(generalTable);
161
        inner.add(generalPanel, "General");
162

    
163
        VerticalPanel permPanel = new VerticalPanel();
164
        FilePropertiesDialog.Images images = GWT.create(FilePropertiesDialog.Images.class);
165
        boolean permsReadonly = folder.getInheritedPermissionsFrom() != null || folder.existChildrenPermissions();
166
        permList = new PermissionsList(images, folder.getPermissions(), folder.getOwner(), permsReadonly);
167
        permPanel.add(permList);
168

    
169
        if (!permsReadonly) {
170
            HorizontalPanel permButtons = new HorizontalPanel();
171
            Button add = new Button("Add Group", new ClickHandler() {
172
                @Override
173
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
174
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
175
                    dlg.center();
176
                }
177
            });
178
            add.addStyleName("button");
179
            permButtons.add(add);
180
            permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);
181

    
182
            Button addUser = new Button("Add User", new ClickHandler() {
183
                @Override
184
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
185
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);
186
                    dlg.center();
187
                }
188
            });
189
            addUser.addStyleName("button");
190
            permButtons.add(addUser);
191
            permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);
192
            permButtons.setSpacing(8);
193
            permPanel.add(permButtons);
194
        }
195

    
196
        if (!create)
197
            inner.add(permPanel, "Sharing");
198
        inner.selectTab(0);
199

    
200
        outer.add(inner);
201

    
202
                // Create the 'Create/Update' button, along with a listener that hides the dialog
203
                // when the button is clicked and quits the application.
204
                String okLabel;
205
                if (create)
206
                        okLabel = "Create";
207
                else
208
                        okLabel = "Update";
209
                Button ok = new Button(okLabel, new ClickHandler() {
210
                        @Override
211
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
212
                                createOrUpdateFolder();
213
                                closeDialog();
214
                        }
215
                });
216
                ok.addStyleName("button");
217
                outer.add(ok);
218
        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);
219

    
220
        setWidget(outer);
221
        }
222

    
223
        @Override
224
        public void center() {
225
                super.center();
226
                folderName.setFocus(true);
227
        }
228

    
229
        @Override
230
        protected void onPreviewNativeEvent(NativePreviewEvent preview) {
231
                super.onPreviewNativeEvent(preview);
232

    
233
                NativeEvent evt = preview.getNativeEvent();
234
                if (evt.getType().equals(KeyDownEvent.getType().getName()))
235
                        // Use the popup's key preview hooks to close the dialog when either
236
                        // enter or escape is pressed.
237
                        switch (evt.getKeyCode()) {
238
                                case KeyCodes.KEY_ENTER:
239
                                        createOrUpdateFolder();
240
                    closeDialog();
241
                                        break;
242
                                case KeyCodes.KEY_ESCAPE:
243
                                        closeDialog();
244
                                        break;
245
                        }
246
        }
247

    
248

    
249
        /**
250
         * Enables IE selection prevention and hides the dialog
251
         * (we disable the prevention on creation of the dialog)
252
         */
253
        public void closeDialog() {
254
                Pithos.preventIESelection();
255
                hide();
256
        }
257

    
258
        /**
259
         * Generate an RPC request to create a new folder.
260
         */
261
        private void createFolder() {
262
                String name = folderName.getText();
263
        String path = folder.getUri() + "/" + name;
264
        PutRequest createFolder = new PutRequest(app.getApiPath(), folder.getOwner(), path) {
265
            @Override
266
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
267
                app.updateFolder(folder, true, new Command() {
268
                                        
269
                                        @Override
270
                                        public void execute() {
271
                                                app.updateStatistics();
272
                                        }
273
                                });
274
            }
275

    
276
            @Override
277
            public void onError(Throwable t) {
278
                                GWT.log("", t);
279
                                if (t instanceof RestException) {
280
                                        app.displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());
281
                                }
282
                                else
283
                                        app.displayError("System error creating folder:" + t.getMessage());
284
            }
285

    
286
                        @Override
287
                        protected void onUnauthorized(Response response) {
288
                                app.sessionExpired();
289
                        }
290
       };
291
        createFolder.setHeader("X-Auth-Token", app.getToken());
292
        createFolder.setHeader("Accept", "*/*");
293
        createFolder.setHeader("Content-Length", "0");
294
        createFolder.setHeader("Content-Type", "application/folder");
295
        Scheduler.get().scheduleDeferred(createFolder);
296
        }
297

    
298
        /**
299
         * Upon closing the dialog by clicking OK or pressing ENTER this method does
300
         * the actual work of modifying folder properties or creating a new Folder
301
         * depending on the value of the create field
302
         */
303
        protected void createOrUpdateFolder() {
304
                if (create)
305
                        createFolder();
306
                else
307
                        updateFolder();
308

    
309
        }
310

    
311
        private void updateFolder() {
312
        final Map<String, Boolean[]> perms = (permList.hasChanges() ? permList.getPermissions() : null);
313
        final String newName = folderName.getText().trim();
314
        if (!folder.isContainer() && !folder.getName().equals(newName)) {
315
            final String path = folder.getParent().getUri() + "/" + newName;
316
            PutRequest newFolder = new PutRequest(app.getApiPath(), folder.getParent().getOwner(), path) {
317
                @Override
318
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
319
                    Iterator<File> iter = folder.getFiles().iterator();
320
                    app.copyFiles(iter, folder.getParent().getOwner(), folder.getParent().getUri() + "/" + newName, new Command() {
321
                        @Override
322
                        public void execute() {
323
                            Iterator<Folder> iterf = folder.getSubfolders().iterator();
324
                            app.copySubfolders(iterf, folder.getParent().getOwner(), folder.getParent().getUri() + "/" + newName, new Command() {
325
                                @Override
326
                                public void execute() {
327
                                    app.deleteFolder(folder);
328
                                    updateMetadata(path + "?update=", perms);
329
                                }
330
                            });
331
                        }
332
                    });
333
                }
334

    
335
                @Override
336
                public void onError(Throwable t) {
337
                    GWT.log("", t);
338
                    if(t instanceof RestException){
339
                        app.displayError("Unable to update folder: " + ((RestException) t).getHttpStatusText());
340
                    }
341
                    else
342
                        app.displayError("System error modifying folder: " + t.getMessage());
343
                }
344

    
345
                                @Override
346
                                protected void onUnauthorized(Response response) {
347
                                        app.sessionExpired();
348
                                }
349
            };
350
            newFolder.setHeader("X-Auth-Token", app.getToken());
351
            newFolder.setHeader("Content-Type", "application/folder");
352
            newFolder.setHeader("Accept", "*/*");
353
            newFolder.setHeader("Content-Length", "0");
354
            Scheduler.get().scheduleDeferred(newFolder);
355
        }
356
        else
357
            updateMetadata(folder.getUri() + "?update=", perms);
358
        }
359

    
360
        protected void updateMetadata(final String path, final Map<String, Boolean[]> newPermissions) {
361
        if (newPermissions != null) {
362
            PostRequest updateFolder = new PostRequest(app.getApiPath(), folder.getOwner(), path) {
363
                @Override
364
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
365
                    app.updateFolder(folder.getParent(), false, null);
366
                }
367

    
368
                @Override
369
                public void onError(Throwable t) {
370
                    GWT.log("", t);
371
                    if (t instanceof RestException) {
372
                            if (((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) { //Probably a virtual folder
373
                            final String path1 = folder.getUri();
374
                            PutRequest newFolder = new PutRequest(app.getApiPath(), folder.getOwner(), path1) {
375
                                @Override
376
                                public void onSuccess(@SuppressWarnings("unused") Resource result) {
377
                                        updateMetadata(path, newPermissions);
378
                                }
379

    
380
                                @Override
381
                                public void onError(Throwable _t) {
382
                                    GWT.log("", _t);
383
                                    if(_t instanceof RestException){
384
                                        app.displayError("Unable to update folder: " + ((RestException) _t).getHttpStatusText());
385
                                    }
386
                                    else
387
                                        app.displayError("System error modifying folder: " + _t.getMessage());
388
                                }
389

    
390
                                                @Override
391
                                                protected void onUnauthorized(Response response) {
392
                                                        app.sessionExpired();
393
                                                }
394
                            };
395
                            newFolder.setHeader("X-Auth-Token", app.getToken());
396
                            newFolder.setHeader("Content-Type", "application/folder");
397
                            newFolder.setHeader("Accept", "*/*");
398
                            newFolder.setHeader("Content-Length", "0");
399
                            Scheduler.get().scheduleDeferred(newFolder);
400
                            }
401
                            else if (((RestException) t).getHttpStatusCode() == Response.SC_CONFLICT) {
402
                                    app.displayError("Cannot set permissions. Probably subfolders or files already have permissions set");
403
                            }
404
                            else
405
                                    app.displayError("Wrror modifying folder: " + t.getMessage());
406
                    }
407
                    else
408
                            app.displayError("System error modifying folder: " + t.getMessage());
409
                }
410

    
411
                                @Override
412
                                protected void onUnauthorized(Response response) {
413
                                        app.sessionExpired();
414
                                }
415
            };
416
            updateFolder.setHeader("X-Auth-Token", app.getToken());
417
            String readPermHeader = "read=";
418
            String writePermHeader = "write=";
419
            for (String u : newPermissions.keySet()) {
420
                Boolean[] p = newPermissions.get(u);
421
                if (p[0] != null && p[0])
422
                    readPermHeader += u + ",";
423
                if (p[1] != null && p[1])
424
                    writePermHeader += u + ",";
425
            }
426
            if (readPermHeader.endsWith("="))
427
                readPermHeader = "";
428
            else if (readPermHeader.endsWith(","))
429
                readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
430
            if (writePermHeader.endsWith("="))
431
                writePermHeader = "";
432
            else if (writePermHeader.endsWith(","))
433
                writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
434
            String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;
435
            if (permHeader.length() == 0)
436
                permHeader="~";
437
            updateFolder.setHeader("X-Object-Sharing", permHeader);
438
            Scheduler.get().scheduleDeferred(updateFolder);
439
        }
440
        else
441
            app.updateFolder(folder.getParent(), false, null);
442
    }
443

    
444
        public void selectTab(int _tab) {
445
                inner.selectTab(_tab);
446
        }
447
}