6e2421fe3377822f16adac00dacdccf86c4fb66c
[pithos] / gss / src / gr / ebs / gss / client / FilePropertiesDialog.java
1 /*\r
2  * Copyright 2007, 2008, 2009 Electronic Business Systems Ltd.\r
3  *\r
4  * This file is part of GSS.\r
5  *\r
6  * GSS is free software: you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation, either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * GSS is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with GSS.  If not, see <http://www.gnu.org/licenses/>.\r
18  */\r
19 package gr.ebs.gss.client;\r
20 \r
21 import gr.ebs.gss.client.rest.ExecuteGet;\r
22 import gr.ebs.gss.client.rest.ExecutePost;\r
23 import gr.ebs.gss.client.rest.RestException;\r
24 import gr.ebs.gss.client.rest.resource.FileResource;\r
25 import gr.ebs.gss.client.rest.resource.FolderResource;\r
26 import gr.ebs.gss.client.rest.resource.GroupResource;\r
27 import gr.ebs.gss.client.rest.resource.GroupUserResource;\r
28 import gr.ebs.gss.client.rest.resource.PermissionHolder;\r
29 import gr.ebs.gss.client.rest.resource.TagsResource;\r
30 \r
31 import java.util.Iterator;\r
32 import java.util.List;\r
33 import java.util.Set;\r
34 \r
35 import com.google.gwt.core.client.GWT;\r
36 import com.google.gwt.i18n.client.DateTimeFormat;\r
37 import com.google.gwt.json.client.JSONArray;\r
38 import com.google.gwt.json.client.JSONBoolean;\r
39 import com.google.gwt.json.client.JSONObject;\r
40 import com.google.gwt.json.client.JSONString;\r
41 import com.google.gwt.user.client.Command;\r
42 import com.google.gwt.user.client.DeferredCommand;\r
43 import com.google.gwt.user.client.Window;\r
44 import com.google.gwt.user.client.ui.AbstractImagePrototype;\r
45 import com.google.gwt.user.client.ui.Button;\r
46 import com.google.gwt.user.client.ui.CheckBox;\r
47 import com.google.gwt.user.client.ui.ClickListener;\r
48 import com.google.gwt.user.client.ui.DialogBox;\r
49 import com.google.gwt.user.client.ui.DisclosurePanel;\r
50 import com.google.gwt.user.client.ui.FlexTable;\r
51 import com.google.gwt.user.client.ui.FlowPanel;\r
52 import com.google.gwt.user.client.ui.FocusPanel;\r
53 import com.google.gwt.user.client.ui.HTML;\r
54 import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
55 import com.google.gwt.user.client.ui.HorizontalPanel;\r
56 import com.google.gwt.user.client.ui.ImageBundle;\r
57 import com.google.gwt.user.client.ui.KeyboardListener;\r
58 import com.google.gwt.user.client.ui.Label;\r
59 import com.google.gwt.user.client.ui.TabPanel;\r
60 import com.google.gwt.user.client.ui.TextBox;\r
61 import com.google.gwt.user.client.ui.VerticalPanel;\r
62 import com.google.gwt.user.client.ui.Widget;\r
63 \r
64 /**\r
65  * The 'File properties' dialog box implementation.\r
66  *\r
67  * @author past\r
68  */\r
69 public class FilePropertiesDialog extends DialogBox {\r
70 \r
71         final PermissionsList permList;\r
72 \r
73         private CheckBox readForAll;\r
74 \r
75         /**\r
76          * An image bundle for this widgets images.\r
77          */\r
78         public interface Images extends ImageBundle {\r
79                 @Resource("gr/ebs/gss/resources/edit_user.png")\r
80                 AbstractImagePrototype permUser();\r
81 \r
82                 @Resource("gr/ebs/gss/resources/groupevent.png")\r
83                 AbstractImagePrototype permGroup();\r
84 \r
85                 @Resource("gr/ebs/gss/resources/editdelete.png")\r
86                 AbstractImagePrototype delete();\r
87 \r
88                 @Resource("gr/ebs/gss/resources/db_update.png")\r
89                 AbstractImagePrototype restore();\r
90 \r
91                 @Resource("gr/ebs/gss/resources/download_manager.png")\r
92                 AbstractImagePrototype download();\r
93         }\r
94 \r
95         /**\r
96          * The widget that holds the name of the file.\r
97          */\r
98         private TextBox name = new TextBox();\r
99 \r
100         /**\r
101          * Text box with the tags associated with the file\r
102          */\r
103         private TextBox tags = new TextBox();\r
104 \r
105         /**\r
106          * A FlowPanel with all user tags\r
107          */\r
108         private FlowPanel allTagsContent;\r
109 \r
110         private String initialTags;\r
111 \r
112         private final CheckBox versioned = new CheckBox();\r
113         final FileResource file;\r
114 \r
115         /**\r
116          * The widget's constructor.\r
117          *\r
118          * @param images the dialog's ImageBundle\r
119          * @param groups\r
120          * @param bodies\r
121          */\r
122         public FilePropertiesDialog(final Images images,  final List<GroupResource> groups,  List<FileResource> bodies) {\r
123                 // Use this opportunity to set the dialog's caption.\r
124                 setText("File properties");\r
125                 setAnimationEnabled(true);\r
126                 file = (FileResource) GSS.get().getCurrentSelection();\r
127                 permList = new PermissionsList(images, file.getPermissions(), file.getOwner());\r
128 \r
129                 // Outer contains inner and buttons\r
130                 final VerticalPanel outer = new VerticalPanel();\r
131                 final FocusPanel focusPanel = new FocusPanel(outer);\r
132                 // Inner contains generalPanel and permPanel\r
133                 final TabPanel inner = new TabPanel();\r
134                 final VerticalPanel generalPanel = new VerticalPanel();\r
135                 final VerticalPanel permPanel = new VerticalPanel();\r
136                 final HorizontalPanel buttons = new HorizontalPanel();\r
137                 final HorizontalPanel permButtons = new HorizontalPanel();\r
138                 final HorizontalPanel permForAll = new HorizontalPanel();\r
139                 final VerticalPanel verPanel = new VerticalPanel();\r
140                 final HorizontalPanel vPanel = new HorizontalPanel();\r
141                 final HorizontalPanel vPanel2 = new HorizontalPanel();\r
142 \r
143                 versioned.setChecked(file.isVersioned());\r
144                 inner.add(generalPanel, "General");\r
145                 inner.add(permPanel, "Permissions");\r
146                 inner.add(verPanel, "Versions");\r
147                 inner.selectTab(0);\r
148 \r
149                 final FlexTable generalTable = new FlexTable();\r
150                 generalTable.setText(0, 0, "Name");\r
151                 generalTable.setText(1, 0, "Folder");\r
152                 generalTable.setText(2, 0, "Owner");\r
153                 generalTable.setText(3, 0, "Date");\r
154                 generalTable.setText(4, 0, "Tags");\r
155                 generalTable.setText(5, 0, "URI");\r
156                 name.setText(file.getName());\r
157                 generalTable.setWidget(0, 1, name);\r
158                 if (GSS.get().getFolders().getCurrent() != null && GSS.get().getFolders().getCurrent().getUserObject() instanceof FolderResource) {\r
159                         FolderResource folder = (FolderResource) GSS.get().getFolders().getCurrent().getUserObject();\r
160                         generalTable.setText(1, 1, folder.getName());\r
161                 } else if (GSS.get().getFolders().getCurrent() != null && GSS.get().getFolders().getCurrent().getUserObject() instanceof GroupUserResource) {\r
162                         GroupUserResource folder = (GroupUserResource) GSS.get().getFolders().getCurrent().getUserObject();\r
163                         generalTable.setText(1, 1, folder.getName());\r
164                 }\r
165                 generalTable.setText(2, 1, file.getOwner());\r
166                 final DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");\r
167                 generalTable.setText(3, 1, formatter.format(file.getCreationDate()));\r
168                 // Get the tags\r
169                 StringBuffer tagsBuffer = new StringBuffer();\r
170                 Iterator i = file.getTags().iterator();\r
171                 while (i.hasNext()) {\r
172                         String tag = (String) i.next();\r
173                         tagsBuffer.append(tag).append(", ");\r
174                 }\r
175                 if (tagsBuffer.length() > 1)\r
176                         tagsBuffer.delete(tagsBuffer.length() - 2, tagsBuffer.length() - 1);\r
177                 tags.setText(tagsBuffer.toString());\r
178                 initialTags = tags.getText();\r
179                 generalTable.setWidget(4, 1, tags);\r
180                 TextBox path = new TextBox();\r
181                 path.setText(file.getPath());\r
182                 path.setTitle("Use this URI for sharing this file with the world");\r
183                 path.setReadOnly(true);\r
184                 generalTable.setWidget(5, 1, path);\r
185                 generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");\r
186                 generalTable.getFlexCellFormatter().setStyleName(1, 0, "props-labels");\r
187                 generalTable.getFlexCellFormatter().setStyleName(2, 0, "props-labels");\r
188                 generalTable.getFlexCellFormatter().setStyleName(3, 0, "props-labels");\r
189                 generalTable.getFlexCellFormatter().setStyleName(4, 0, "props-labels");\r
190                 generalTable.getFlexCellFormatter().setStyleName(5, 0, "props-labels");\r
191                 generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");\r
192                 generalTable.getFlexCellFormatter().setStyleName(1, 1, "props-values");\r
193                 generalTable.getFlexCellFormatter().setStyleName(2, 1, "props-values");\r
194                 generalTable.getFlexCellFormatter().setStyleName(3, 1, "props-values");\r
195                 generalTable.getFlexCellFormatter().setStyleName(4, 1, "props-values");\r
196                 generalTable.getFlexCellFormatter().setStyleName(5, 1, "props-values");\r
197                 generalTable.setCellSpacing(4);\r
198 \r
199                 // Create the 'OK' button, along with a listener that hides the dialog\r
200                 // when the button is clicked.\r
201                 final Button ok = new Button("OK", new ClickListener() {\r
202 \r
203                         public void onClick(Widget sender) {\r
204                                 accept();\r
205                                 hide();\r
206                         }\r
207                 });\r
208                 buttons.add(ok);\r
209                 buttons.setCellHorizontalAlignment(ok, HasHorizontalAlignment.ALIGN_CENTER);\r
210                 // Create the 'Cancel' button, along with a listener that hides the\r
211                 // dialog\r
212                 // when the button is clicked.\r
213                 final Button cancel = new Button("Cancel", new ClickListener() {\r
214 \r
215                         public void onClick(Widget sender) {\r
216                                 hide();\r
217                         }\r
218                 });\r
219                 buttons.add(cancel);\r
220                 buttons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);\r
221                 buttons.setSpacing(8);\r
222                 buttons.addStyleName("gwt-TabPanelBottom");\r
223 \r
224                 generalPanel.add(generalTable);\r
225 \r
226                 // Asynchronously retrieve the tags defined by this user\r
227                 DeferredCommand.addCommand(new Command() {\r
228 \r
229                         public void execute() {\r
230                                 updateTags();\r
231                         }\r
232                 });\r
233 \r
234                 DisclosurePanel allTags = new DisclosurePanel("All tags");\r
235                 allTagsContent = new FlowPanel();\r
236                 allTags.setContent(allTagsContent);\r
237                 generalPanel.add(allTags);\r
238                 generalPanel.setSpacing(4);\r
239 \r
240                 final Button add = new Button("Add Group", new ClickListener() {\r
241 \r
242                         public void onClick(Widget sender) {\r
243                                 // hide();\r
244                                 PermissionsAddDialog dlg = new PermissionsAddDialog(images, groups, permList, false);\r
245                                 dlg.center();\r
246                         }\r
247                 });\r
248                 permButtons.add(add);\r
249                 permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
250 \r
251                 final Button addUser = new Button("Add User", new ClickListener() {\r
252 \r
253                         public void onClick(Widget sender) {\r
254                                 // hide();\r
255                                 PermissionsAddDialog dlg = new PermissionsAddDialog(images, groups, permList, true);\r
256                                 dlg.center();\r
257                         }\r
258                 });\r
259                 permButtons.add(addUser);\r
260                 permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);\r
261 \r
262                 permButtons.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);\r
263                 permButtons.setSpacing(8);\r
264                 permButtons.addStyleName("gwt-TabPanelBottom");\r
265 \r
266                 final Label readForAllNote = new Label("When this option is enabled, the file will be readable" +\r
267                                 " by everyone. By checking this option, you are certifying that you have the right to " +\r
268                                 "distribute this file and that it does not violate the Terms of Use.", true);\r
269                 readForAllNote.setVisible(false);\r
270                 readForAllNote.setStylePrimaryName("gss-readForAllNote");\r
271 \r
272                 readForAll = new CheckBox();\r
273                 readForAll.setChecked(file.isReadForAll());\r
274                 readForAll.addClickListener(new ClickListener() {\r
275 \r
276                         public void onClick(Widget sender) {\r
277                                 if (readForAll.isChecked())\r
278                                         readForAllNote.setVisible(true);\r
279                                 else\r
280                                         readForAllNote.setVisible(false);\r
281                         }\r
282 \r
283                 });\r
284                 permForAll.add(new Label("Read For All:"));\r
285                 permForAll.add(readForAll);\r
286                 permForAll.setSpacing(8);\r
287                 permForAll.addStyleName("gwt-TabPanelBottom");\r
288                 permPanel.add(permList);\r
289                 permPanel.add(permButtons);\r
290                 permPanel.add(permForAll);\r
291                 permPanel.add(readForAllNote);\r
292 \r
293                 VersionsList verList = new VersionsList(this, images, bodies);\r
294                 verPanel.add(verList);\r
295 \r
296                 vPanel.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);\r
297                 vPanel.setSpacing(8);\r
298                 vPanel.addStyleName("gwt-TabPanelBottom");\r
299                 vPanel.add(new Label("Versioned:"));\r
300 \r
301                 vPanel.add(versioned);\r
302                 verPanel.add(vPanel);\r
303                 vPanel2.setCellHorizontalAlignment(cancel, HasHorizontalAlignment.ALIGN_CENTER);\r
304                 vPanel2.setSpacing(8);\r
305                 vPanel2.addStyleName("gwt-TabPanelBottom");\r
306                 Button removeVersionsButton = new Button(images.delete().getHTML(),new ClickListener(){\r
307 \r
308                         public void onClick(Widget sender) {\r
309                                 //TODO: replace javascript confirmation dialog\r
310                                 boolean confirm = Window.confirm("Really remove all previous versions?");\r
311                                 if(confirm)\r
312                                         hide();\r
313                                         removeAllOldVersions();\r
314 \r
315                         }\r
316 \r
317 \r
318 \r
319                 });\r
320                 HTML removeAllVersion = new HTML("<span>Remove all previous versions?</span>");\r
321                 vPanel2.add(removeAllVersion);\r
322                 vPanel2.add(removeVersionsButton);\r
323                 verPanel.add(vPanel2);\r
324                 outer.add(inner);\r
325                 outer.add(buttons);\r
326                 outer.setCellHorizontalAlignment(buttons, HasHorizontalAlignment.ALIGN_CENTER);\r
327                 outer.addStyleName("gwt-TabPanelBottom");\r
328 \r
329                 focusPanel.setFocus(true);\r
330                 setWidget(outer);\r
331         }\r
332 \r
333         /**\r
334          * Retrieves all user tags from the server and updates the FlowPanel\r
335          *\r
336          * @param userId\r
337          */\r
338         private void updateTags() {\r
339                 ExecuteGet<TagsResource> tc = new ExecuteGet<TagsResource>(TagsResource.class, GSS.get().getCurrentUserResource().getTagsPath()){\r
340 \r
341                         public void onComplete() {\r
342                                 allTagsContent.clear();\r
343                                 TagsResource tagr = getResult();\r
344                                 List<String> userTags = tagr.getTags();\r
345                                 Iterator t = userTags.iterator();\r
346                                 while (t.hasNext()) {\r
347                                         final Button tag = new Button((String) t.next(), new ClickListener() {\r
348 \r
349                                                 public void onClick(Widget sender) {\r
350                                                         String existing = tags.getText();\r
351                                                         String newTag = ((Button) sender).getText().trim();\r
352                                                         // insert the new tag only if it is not in the list\r
353                                                         // already\r
354                                                         if (existing.indexOf(newTag + ",") == -1 && !existing.trim().endsWith(newTag))\r
355                                                                 tags.setText(existing.trim() + (existing.length() > 0 ? ", " : "") + newTag);\r
356                                                 }\r
357                                         });\r
358                                         allTagsContent.add(tag);\r
359                                 }\r
360                         }\r
361 \r
362                         @Override\r
363                         public void onError(Throwable t) {\r
364                                 GWT.log("", t);\r
365                                 GSS.get().displayError("Unable to fetch user tags");\r
366                         }\r
367                 };\r
368                 DeferredCommand.addCommand(tc);\r
369 \r
370         }\r
371 \r
372         @Override\r
373         @SuppressWarnings("fallthrough")\r
374         public boolean onKeyDownPreview(char key, int modifiers) {\r
375                 // Use the popup's key preview hooks to close the dialog when either\r
376                 // enter or escape is pressed.\r
377                 switch (key) {\r
378                         case KeyboardListener.KEY_ENTER:\r
379                                 accept();\r
380                         case KeyboardListener.KEY_ESCAPE:\r
381                                 hide();\r
382                                 break;\r
383                 }\r
384 \r
385                 return true;\r
386         }\r
387 \r
388         /**\r
389          * Accepts any change and updates the file\r
390          *\r
391          * @param userId\r
392          */\r
393         private void accept() {\r
394                 permList.updatePermissionsAccordingToInput();\r
395                 Set<PermissionHolder> perms = permList.getPermissions();\r
396                 JSONObject json = new JSONObject();\r
397                 json.put("name", new JSONString(name.getText()));\r
398                 json.put("versioned", JSONBoolean.getInstance(versioned.isChecked()));\r
399                 json.put("readForAll", JSONBoolean.getInstance(readForAll.isChecked()));\r
400                 JSONArray perma = new JSONArray();\r
401                 int i=0;\r
402                 for(PermissionHolder p : perms){\r
403                         JSONObject po = new JSONObject();\r
404                         if(p.getUser() != null)\r
405                                 po.put("user", new JSONString(p.getUser()));\r
406                         if(p.getGroup() != null)\r
407                                 po.put("group", new JSONString(p.getGroup()));\r
408                         po.put("read", JSONBoolean.getInstance(p.isRead()));\r
409                         po.put("write", JSONBoolean.getInstance(p.isWrite()));\r
410                         po.put("modifyACL", JSONBoolean.getInstance(p.isModifyACL()));\r
411                         perma.set(i,po);\r
412                         i++;\r
413                 }\r
414                 json.put("permissions", perma);\r
415                 JSONArray taga = new JSONArray();\r
416                 i=0;\r
417                 String[] tagset = tags.getText().split(",");\r
418                 for(String t : tagset){\r
419                         JSONString to = new JSONString(t);\r
420                         taga.set(i,to);\r
421                         i++;\r
422                 }\r
423                 json.put("tags", taga);\r
424                 GWT.log(json.toString(), null);\r
425                 ExecutePost cf = new ExecutePost(file.getPath()+"?update=",json.toString(), 200){\r
426                         public void onComplete() {\r
427                                 GSS.get().getFileList().updateFileCache(true);\r
428                         }\r
429 \r
430 \r
431                         public void onError(Throwable t) {\r
432                                 GWT.log("", t);\r
433                                 if(t instanceof RestException){\r
434                                         int statusCode = ((RestException)t).getHttpStatusCode();\r
435                                         if(statusCode == 405)\r
436                                                 GSS.get().displayError("You don't have the necessary permissions");\r
437                                         else if(statusCode == 404)\r
438                                                 GSS.get().displayError("User in permissions does not exist");\r
439                                         else if(statusCode == 409)\r
440                                                 GSS.get().displayError("A file with the same name already exists");\r
441                                         else if(statusCode == 413)\r
442                                                 GSS.get().displayError("Your quota has been exceeded");\r
443                                         else\r
444                                                 GSS.get().displayError("Unable to modify file, status code:"+statusCode);\r
445                                 }\r
446                                 else\r
447                                         GSS.get().displayError("System error modifying file:"+t.getMessage());\r
448                         }\r
449 \r
450                 };\r
451                 DeferredCommand.addCommand(cf);\r
452 \r
453 \r
454         }\r
455 \r
456 \r
457         private void removeAllOldVersions() {\r
458                 toggleVersioned(false);\r
459                 toggleVersioned(true);\r
460         }\r
461 \r
462         private void toggleVersioned(boolean versionedValue){\r
463                 JSONObject json = new JSONObject();\r
464                 json.put("versioned", JSONBoolean.getInstance(versionedValue));\r
465                 GWT.log(json.toString(), null);\r
466                 ExecutePost cf = new ExecutePost(file.getPath()+"?update=",json.toString(), 200){\r
467                         public void onComplete() {\r
468                                 GSS.get().getFileList().updateFileCache(true);\r
469                         }\r
470 \r
471                         public void onError(Throwable t) {\r
472                                 GWT.log("", t);\r
473                                 if(t instanceof RestException){\r
474                                         int statusCode = ((RestException)t).getHttpStatusCode();\r
475                                         if(statusCode == 405)\r
476                                                 GSS.get().displayError("You don't have the necessary permissions");\r
477                                         else if(statusCode == 404)\r
478                                                 GSS.get().displayError("User in permissions does not exist");\r
479                                         else if(statusCode == 409)\r
480                                                 GSS.get().displayError("A folder with the same name already exists");\r
481                                         else if(statusCode == 413)\r
482                                                 GSS.get().displayError("Your quota has been exceeded");\r
483                                         else\r
484                                                 GSS.get().displayError("Unable to modify file, status code:"+statusCode);\r
485                                 }\r
486                                 else\r
487                                         GSS.get().displayError("System error moifying file:"+t.getMessage());\r
488                         }\r
489                 };\r
490                 DeferredCommand.addCommand(cf);\r
491         }\r
492 \r
493 }\r