Statistics
| Branch: | Tag: | Revision:

root / web_client / src / gr / grnet / pithos / web / client / FolderPropertiesDialog.java @ dac23cda

History | View | Annotate | Download (17.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 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.Button;
56
import com.google.gwt.user.client.ui.DecoratedTabPanel;
57
import com.google.gwt.user.client.ui.DialogBox;
58
import com.google.gwt.user.client.ui.FlexTable;
59
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
60
import com.google.gwt.user.client.ui.HorizontalPanel;
61
import com.google.gwt.user.client.ui.TabPanel;
62
import com.google.gwt.user.client.ui.TextBox;
63
import com.google.gwt.user.client.ui.VerticalPanel;
64
import java.util.Iterator;
65
import java.util.Map;
66

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

    
72
    protected Pithos app;
73

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

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

    
85
        protected PermissionsList permList;
86

    
87
        final Folder folder;
88

    
89
        final TabPanel inner;
90

    
91
        /**
92
         * The widget's constructor.
93
         */
94
        public FolderPropertiesDialog(final Pithos app, boolean _create,  Folder selected) {
95
        this.app = app;
96
                setAnimationEnabled(true);
97

    
98
                // Enable IE selection for the dialog (must disable it upon closing it)
99
                Pithos.enableIESelection();
100

    
101
                create = _create;
102
                
103
                folder = selected;
104

    
105
                // Use this opportunity to set the dialog's caption.
106
                if (create)
107
                        setText("Create folder");
108
                else
109
                        setText("Folder properties");
110

    
111
                // Outer contains inner and buttons
112
                VerticalPanel outer = new VerticalPanel();
113
                // Inner contains generalPanel and permPanel
114
                inner = new DecoratedTabPanel();
115
                inner.setAnimationEnabled(true);
116

    
117
                VerticalPanel generalPanel = new VerticalPanel();
118
        FlexTable generalTable = new FlexTable();
119
        generalTable.setText(0, 0, "Name");
120
        generalTable.setText(1, 0, "Parent");
121
        generalTable.setText(2, 0, "Creator");
122
        generalTable.setText(3, 0, "Last modified");
123
        folderName.setText(create ? "" : folder.getName());
124
        folderName.setReadOnly(folder.isContainer() && !create);
125
        generalTable.setWidget(0, 1, folderName);
126

    
127
        if (create)
128
            generalTable.setText(1, 1, folder.getName());
129
        else
130
            generalTable.setText(1, 1, folder.getPrefix());
131
        generalTable.setText(2, 1, "");
132
        DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");
133
        if(folder.getLastModified() != null)
134
            generalTable.setText(3, 1, formatter.format(folder.getLastModified()));
135
        generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");
136
        generalTable.getFlexCellFormatter().setStyleName(1, 0, "props-labels");
137
        generalTable.getFlexCellFormatter().setStyleName(2, 0, "props-labels");
138
        generalTable.getFlexCellFormatter().setStyleName(3, 0, "props-labels");
139
        generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");
140
        generalTable.getFlexCellFormatter().setStyleName(1, 1, "props-values");
141
        generalTable.getFlexCellFormatter().setStyleName(2, 1, "props-values");
142
        generalTable.getFlexCellFormatter().setStyleName(3, 1, "props-values");
143
        generalTable.setCellSpacing(4);
144
        generalPanel.add(generalTable);
145
        inner.add(generalPanel, "General");
146

    
147
        VerticalPanel permPanel = new VerticalPanel();
148
        FilePropertiesDialog.Images images = GWT.create(FilePropertiesDialog.Images.class);
149
        boolean permsReadonly = folder.getInheritedPermissionsFrom() != null || folder.existChildrenPermissions();
150
        permList = new PermissionsList(images, folder.getPermissions(), folder.getOwner(), permsReadonly);
151
        permPanel.add(permList);
152

    
153
        if (!permsReadonly) {
154
            HorizontalPanel permButtons = new HorizontalPanel();
155
            Button add = new Button("Add Group", new ClickHandler() {
156
                @Override
157
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
158
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);
159
                    dlg.center();
160
                }
161
            });
162
            permButtons.add(add);
163
            permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);
164

    
165
            Button addUser = new Button("Add User", new ClickHandler() {
166
                @Override
167
                public void onClick(@SuppressWarnings("unused") ClickEvent event) {
168
                    PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);
169
                    dlg.center();
170
                }
171
            });
172
            addUser.getElement().setId("folderPropertiesDialog.button.addUser");
173
            permButtons.add(addUser);
174
            permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);
175
            permButtons.setSpacing(8);
176
            permButtons.addStyleName("gss-TabPanelBottom");
177
            permPanel.add(permButtons);
178
        }
179

    
180
        if (!create)
181
            inner.add(permPanel, "Sharing");
182
        inner.selectTab(0);
183

    
184
        outer.add(inner);
185

    
186
        HorizontalPanel buttons = new HorizontalPanel();
187
                // Create the 'Create/Update' button, along with a listener that hides the dialog
188
                // when the button is clicked and quits the application.
189
                String okLabel;
190
                if (create)
191
                        okLabel = "Create";
192
                else
193
                        okLabel = "Update";
194
                Button ok = new Button(okLabel, new ClickHandler() {
195
                        @Override
196
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
197
                                createOrUpdateFolder();
198
                                closeDialog();
199
                        }
200
                });
201
                buttons.add(ok);
202
                buttons.setCellHorizontalAlignment(ok, HasHorizontalAlignment.ALIGN_CENTER);
203
                // Create the 'Cancel' button, along with a listener that hides the
204
                // dialog
205
                // when the button is clicked.
206
                Button cancel = new Button("Cancel", new ClickHandler() {
207
                        @Override
208
                        public void onClick(@SuppressWarnings("unused") ClickEvent event) {
209
                                closeDialog();
210
                        }
211
                });
212
                buttons.add(cancel);
213
                buttons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);
214
                buttons.setSpacing(8);
215
                buttons.addStyleName("pithos-TabPanelBottom");
216
        outer.add(buttons);
217
        outer.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER);
218
        outer.addStyleName("pithos-TabPanelBottom");
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(), app.getUsername(), path) {
265
            @Override
266
            public void onSuccess(@SuppressWarnings("unused") Resource result) {
267
                app.updateFolder(folder, true, null);
268
            }
269

    
270
            @Override
271
            public void onError(Throwable t) {
272
                                GWT.log("", t);
273
                                if (t instanceof RestException) {
274
                                        app.displayError("Unable to create folder:" + ((RestException) t).getHttpStatusText());
275
                                }
276
                                else
277
                                        app.displayError("System error creating folder:" + t.getMessage());
278
            }
279
        };
280
        createFolder.setHeader("X-Auth-Token", app.getToken());
281
        createFolder.setHeader("Accept", "*/*");
282
        createFolder.setHeader("Content-Length", "0");
283
        createFolder.setHeader("Content-Type", "application/folder");
284
        Scheduler.get().scheduleDeferred(createFolder);
285
        }
286

    
287
        /**
288
         * Upon closing the dialog by clicking OK or pressing ENTER this method does
289
         * the actual work of modifying folder properties or creating a new Folder
290
         * depending on the value of the create field
291
         */
292
        protected void createOrUpdateFolder() {
293
                if (create)
294
                        createFolder();
295
                else
296
                        updateFolder();
297

    
298
        }
299

    
300
        private void updateFolder() {
301
        final Map<String, Boolean[]> perms = (permList.hasChanges() ? permList.getPermissions() : null);
302
        final String newName = folderName.getText().trim();
303
        if (!folder.isContainer() && !folder.getName().equals(newName)) {
304
            final String path = folder.getParent().getUri() + "/" + newName;
305
            PutRequest newFolder = new PutRequest(app.getApiPath(), app.getUsername(), path) {
306
                @Override
307
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
308
                    Iterator<File> iter = folder.getFiles().iterator();
309
                    app.copyFiles(iter, folder.getParent().getUri() + "/" + newName, new Command() {
310
                        @Override
311
                        public void execute() {
312
                            Iterator<Folder> iterf = folder.getSubfolders().iterator();
313
                            app.copySubfolders(iterf, folder.getParent().getUri() + "/" + newName, new Command() {
314
                                @Override
315
                                public void execute() {
316
                                    app.deleteFolder(folder);
317
                                    updateMetadata(path + "?update=", perms);
318
                                }
319
                            });
320
                        }
321
                    });
322
                }
323

    
324
                @Override
325
                public void onError(Throwable t) {
326
                    GWT.log("", t);
327
                    if(t instanceof RestException){
328
                        app.displayError("Unable to update folder: " + ((RestException) t).getHttpStatusText());
329
                    }
330
                    else
331
                        app.displayError("System error modifying folder: " + t.getMessage());
332
                }
333
            };
334
            newFolder.setHeader("X-Auth-Token", app.getToken());
335
            newFolder.setHeader("Content-Type", "application/folder");
336
            newFolder.setHeader("Accept", "*/*");
337
            newFolder.setHeader("Content-Length", "0");
338
            Scheduler.get().scheduleDeferred(newFolder);
339
        }
340
        else
341
            updateMetadata(folder.getUri() + "?update=", perms);
342
        }
343

    
344
        protected void updateMetadata(final String path, final Map<String, Boolean[]> newPermissions) {
345
        if (newPermissions != null) {
346
            PostRequest updateFolder = new PostRequest(app.getApiPath(), folder.getOwner(), path) {
347
                @Override
348
                public void onSuccess(@SuppressWarnings("unused") Resource result) {
349
                    app.updateFolder(folder.getParent(), false, null);
350
                }
351

    
352
                @Override
353
                public void onError(Throwable t) {
354
                    GWT.log("", t);
355
                    if (t instanceof RestException) {
356
                            if (((RestException) t).getHttpStatusCode() == Response.SC_NOT_FOUND) { //Probably a virtual folder
357
                            final String path1 = folder.getUri();
358
                            PutRequest newFolder = new PutRequest(app.getApiPath(), app.getUsername(), path1) {
359
                                @Override
360
                                public void onSuccess(@SuppressWarnings("unused") Resource result) {
361
                                        updateMetadata(path, newPermissions);
362
                                }
363

    
364
                                @Override
365
                                public void onError(Throwable t) {
366
                                    GWT.log("", t);
367
                                    if(t instanceof RestException){
368
                                        app.displayError("Unable to update folder: " + ((RestException) t).getHttpStatusText());
369
                                    }
370
                                    else
371
                                        app.displayError("System error modifying folder: " + t.getMessage());
372
                                }
373
                            };
374
                            newFolder.setHeader("X-Auth-Token", app.getToken());
375
                            newFolder.setHeader("Content-Type", "application/folder");
376
                            newFolder.setHeader("Accept", "*/*");
377
                            newFolder.setHeader("Content-Length", "0");
378
                            Scheduler.get().scheduleDeferred(newFolder);
379
                            }
380
                    }
381
                    else
382
                            app.displayError("System error modifying folder: " + t.getMessage());
383
                }
384
            };
385
            updateFolder.setHeader("X-Auth-Token", app.getToken());
386
            String readPermHeader = "read=";
387
            String writePermHeader = "write=";
388
            for (String u : newPermissions.keySet()) {
389
                Boolean[] p = newPermissions.get(u);
390
                if (p[0] != null && p[0])
391
                    readPermHeader += u + ",";
392
                if (p[1] != null && p[1])
393
                    writePermHeader += u + ",";
394
            }
395
            if (readPermHeader.endsWith("="))
396
                readPermHeader = "";
397
            else if (readPermHeader.endsWith(","))
398
                readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);
399
            if (writePermHeader.endsWith("="))
400
                writePermHeader = "";
401
            else if (writePermHeader.endsWith(","))
402
                writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);
403
            String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;
404
            if (permHeader.length() == 0)
405
                permHeader="~";
406
            updateFolder.setHeader("X-Object-Sharing", permHeader);
407
            Scheduler.get().scheduleDeferred(updateFolder);
408
        }
409
        else
410
            app.updateFolder(folder.getParent(), false, null);
411
    }
412

    
413
        public void selectTab(int _tab) {
414
                inner.selectTab(_tab);
415
        }
416
}