Merge branch 'packaging' into debian
authorKostas Papadimitriou <kpap@grnet.gr>
Mon, 7 May 2012 11:01:14 +0000 (14:01 +0300)
committerKostas Papadimitriou <kpap@grnet.gr>
Mon, 7 May 2012 11:01:14 +0000 (14:01 +0300)
54 files changed:
docs/source/conf.py
docs/source/index.rst
docs/source/webclient.rst
src/gr/grnet/pithos/resources/2folder22.png [new file with mode: 0644]
src/gr/grnet/pithos/resources/delete.gif [new file with mode: 0644]
src/gr/grnet/pithos/resources/sharedbyme22.png [new file with mode: 0644]
src/gr/grnet/pithos/resources/sharedtome22.png [new file with mode: 0644]
src/gr/grnet/pithos/web/Pithos.gwt.xml
src/gr/grnet/pithos/web/client/AbstractPropertiesDialog.java
src/gr/grnet/pithos/web/client/AddUserDialog.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/ConfirmationDialog.java
src/gr/grnet/pithos/web/client/CredentialsDialog.java
src/gr/grnet/pithos/web/client/DeleteFileDialog.java
src/gr/grnet/pithos/web/client/DeleteFolderDialog.java
src/gr/grnet/pithos/web/client/FeedbackDialog.java
src/gr/grnet/pithos/web/client/FileContextMenu.java
src/gr/grnet/pithos/web/client/FileList.java
src/gr/grnet/pithos/web/client/FilePermissionsDialog.java
src/gr/grnet/pithos/web/client/FilePropertiesDialog.java
src/gr/grnet/pithos/web/client/FilePublishDialog.java
src/gr/grnet/pithos/web/client/FileUploadDialog.java
src/gr/grnet/pithos/web/client/FileVersionsDialog.java
src/gr/grnet/pithos/web/client/FilesPropertiesDialog.java
src/gr/grnet/pithos/web/client/FolderContextMenu.java
src/gr/grnet/pithos/web/client/FolderPermissionsDialog.java
src/gr/grnet/pithos/web/client/FolderPropertiesDialog.java
src/gr/grnet/pithos/web/client/GroupCreateDialog.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/PermissionsAddDialog.java
src/gr/grnet/pithos/web/client/PermissionsList.java
src/gr/grnet/pithos/web/client/Pithos.java
src/gr/grnet/pithos/web/client/PithosCellTable.css
src/gr/grnet/pithos/web/client/PithosCellTreeBasic.css
src/gr/grnet/pithos/web/client/PithosDisclosurePanel.css [new file with mode: 0644]
src/gr/grnet/pithos/web/client/PithosDisclosurePanel.java [new file with mode: 0644]
src/gr/grnet/pithos/web/client/Toolbar.java
src/gr/grnet/pithos/web/client/ToolsMenu.java
src/gr/grnet/pithos/web/client/commands/AddUserCommand.java
src/gr/grnet/pithos/web/client/commands/CreateGroupCommand.java
src/gr/grnet/pithos/web/client/commands/RefreshCommand.java
src/gr/grnet/pithos/web/client/foldertree/File.java
src/gr/grnet/pithos/web/client/foldertree/FolderTreeView.java
src/gr/grnet/pithos/web/client/foldertree/FolderTreeViewModel.java
src/gr/grnet/pithos/web/client/grouptree/GroupTreeView.java
src/gr/grnet/pithos/web/client/grouptree/GroupTreeViewModel.java
src/gr/grnet/pithos/web/client/grouptree/PithosGroupDisclosurePanel.css [new file with mode: 0644]
src/gr/grnet/pithos/web/client/mysharedtree/MysharedTreeView.java
src/gr/grnet/pithos/web/client/mysharedtree/MysharedTreeViewModel.java
src/gr/grnet/pithos/web/client/mysharedtree/PithosMySharedDisclosurePanel.css [new file with mode: 0644]
src/gr/grnet/pithos/web/client/othersharedtree/OtherSharedTreeView.java
src/gr/grnet/pithos/web/client/othersharedtree/OtherSharedTreeViewModel.java
src/gr/grnet/pithos/web/client/othersharedtree/PithosOtherSharedDisclosurePanel.css [new file with mode: 0644]
src/gr/grnet/pithos/web/public/images/separator.png [new file with mode: 0644]
src/gr/grnet/pithos/web/public/pithos.css
src/gr/grnet/pithos/web/public/plupload/js/jquery.plupload.queue/css/jquery.plupload.queue.css

index c200856..431a958 100644 (file)
@@ -182,6 +182,80 @@ latex_documents = [
    u'GRNet', 'manual'),
 ]
 
+
+PREAMBLE = """
+\makeatletter
+    \\fancypagestyle{normal}{
+        \\fancyhf{}
+        \\fancyfoot[RO,LE]{{\py@HeaderFamily\\thepage}}
+        \\fancyfoot[LO]{{\py@HeaderFamily\\nouppercase{\\rightmark}}}
+        \\fancyfoot[RE]{{\py@HeaderFamily\\nouppercase{\leftmark}}}
+        \\fancyhead[LE,RO]{{\py@HeaderFamily \@title, \py@release}}
+        \\fancyhead[LO,RE]{\includegraphics[width=3cm]{../../espa.jpg}}
+    }
+
+
+\\renewcommand{\maketitle}{%
+  \\begin{titlepage}%
+    \let\\footnotesize\small
+    \let\\footnoterule\\relax
+    \\rule{\\textwidth}{1pt}%
+    \ifsphinxpdfoutput
+      \\begingroup
+      % These \defs are required to deal with multi-line authors; it
+      % changes \\\\ to ', ' (comma-space), making it pass muster for
+      % generating document info in the PDF file.
+      \def\\\\{, }
+      \def\\and{and }
+      \pdfinfo{
+        /Author (\@author)
+        /Title (\@title)
+      }
+      \endgroup
+    \\fi
+    \\begin{flushright}%
+      \sphinxlogo%
+      {\\rm\Huge\py@HeaderFamily \@title \par}%
+      {\em\LARGE\py@HeaderFamily \py@release\\releaseinfo \par}
+      \\vfill
+      {\LARGE\py@HeaderFamily
+        \\begin{tabular}[t]{c}
+          \@author
+        \end{tabular}
+        \par}
+      \\vfill\\vfill
+      {\large
+       \@date \par
+       \includegraphics[width=6cm]{../../espa.jpg}
+       \\vfill
+       \py@authoraddress \par
+      }%
+    \end{flushright}%\par
+    \@thanks
+  \end{titlepage}%
+  \cleardoublepage%
+  \setcounter{footnote}{0}%
+  \let\\thanks\\relax\let\maketitle\\relax
+  %\gdef\@thanks{}\gdef\@author{}\gdef\@title{}
+}
+\makeatother
+"""
+
+latex_elements = {
+# The paper size ('letterpaper' or 'a4paper').
+#'papersize': 'letterpaper',
+
+# The font size ('10pt', '11pt' or '12pt').
+#'pointsize': '10pt',
+
+# Additional stuff for the LaTeX preamble.
+'preamble': PREAMBLE,
+
+'classoptions': ',openany,oneside',
+
+'babel': '\\usepackage[english]{babel}'
+}
+
 # The name of an image file (relative to this directory) to place at the top of
 # the title page.
 #latex_logo = None
index 8745bda..864e470 100644 (file)
@@ -13,10 +13,3 @@ Contents:
 
    webclient
 
-Indices and tables
-==================
-
-* :ref:`genindex`
-* :ref:`modindex`
-* :ref:`search`
-
index b4e89ed..5758b07 100644 (file)
@@ -168,7 +168,7 @@ GET /v1/username/container?format=json&delimiter=/&prefix=subfolder
 
 and this is done recursively until all shared folders have been collected.
 
-Constructing the "Shared by others" tree
+Constructing the "Shared to me" tree
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 The "Shared by others" tree has the additional complication that we need to get the users that share objects with us and display them as a first level of subfolders.
 
@@ -232,7 +232,11 @@ File Operations
 ^^^^^^^^^^^^^^^
 File uploading
 """"""""""""""
-File uploading is done using the plupload http://www.plupload.com/ plugin.
+File uploading is done using the plupload http://www.plupload.com/ plugin. The plugin supports multiple file upload, drag'n'drop from the desktop and progress indication. It uses any of the following technolgies (whatever is available in the browser) html5, flash, gears, silverlight, browserplus, html4 in this order. If none is found then html4 is the last fallback in which case most features are not available (no drag'n'drop, no progress indicator).
+
+The upload operation is done with a 
+
+POST /v1/username/container/path/to/file?X-Auth-Token=<auth token>. This is the only case the auth token is passed as a url parameter. The reason is that it cannot be passed as a header due to the fact that the POST is not controlled by the code, it cannot be passed as POST payload parameter (form parameter) for efficiency reasons (the server should read the whole file first, before reading the token) and it cannot be passed as a cookie to avoid XSRF attacks.
 
 File rename
 """""""""""
diff --git a/src/gr/grnet/pithos/resources/2folder22.png b/src/gr/grnet/pithos/resources/2folder22.png
new file mode 100644 (file)
index 0000000..1e9df8c
Binary files /dev/null and b/src/gr/grnet/pithos/resources/2folder22.png differ
diff --git a/src/gr/grnet/pithos/resources/delete.gif b/src/gr/grnet/pithos/resources/delete.gif
new file mode 100644 (file)
index 0000000..78ca8b3
Binary files /dev/null and b/src/gr/grnet/pithos/resources/delete.gif differ
diff --git a/src/gr/grnet/pithos/resources/sharedbyme22.png b/src/gr/grnet/pithos/resources/sharedbyme22.png
new file mode 100644 (file)
index 0000000..54e3a51
Binary files /dev/null and b/src/gr/grnet/pithos/resources/sharedbyme22.png differ
diff --git a/src/gr/grnet/pithos/resources/sharedtome22.png b/src/gr/grnet/pithos/resources/sharedtome22.png
new file mode 100644 (file)
index 0000000..81a8f95
Binary files /dev/null and b/src/gr/grnet/pithos/resources/sharedtome22.png differ
index bff8fd7..bbe984a 100644 (file)
@@ -38,6 +38,7 @@
     <inherits name="com.google.gwt.user.theme.standard.Standard"/>
        <inherits name="com.google.gwt.http.HTTP"/>
        <inherits name="com.google.gwt.json.JSON"/>
+       <inherits name="com.google.gwt.resources.Resources"/>
 
     <entry-point class='gr.grnet.pithos.web.client.Pithos' />
        <stylesheet src='pithos.css' />
index e3a125c..0c53546 100644 (file)
@@ -67,9 +67,10 @@ public abstract class AbstractPropertiesDialog extends DialogBox {
 \r
        /**\r
         * Accepts any change and updates the file\r
+        * @return \r
         *\r
         */\r
-       protected abstract void accept();\r
+       protected abstract boolean accept();\r
 \r
        @Override\r
        protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
@@ -81,8 +82,9 @@ public abstract class AbstractPropertiesDialog extends DialogBox {
                          // enter or escape is pressed.\r
                          switch (evt.getKeyCode()) {\r
                            case KeyCodes.KEY_ENTER:\r
-                               accept();\r
-                           //$FALL-THROUGH$\r
+                               if (accept())\r
+                                       closeDialog();\r
+                               break;\r
                        case KeyCodes.KEY_ESCAPE:\r
                                closeDialog();\r
                                break;\r
diff --git a/src/gr/grnet/pithos/web/client/AddUserDialog.java b/src/gr/grnet/pithos/web/client/AddUserDialog.java
new file mode 100644 (file)
index 0000000..186a036
--- /dev/null
@@ -0,0 +1,214 @@
+/*\r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ *   1. Redistributions of source code must retain the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer.\r
+ *\r
+ *   2. Redistributions in binary form must reproduce the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer in the documentation and/or other materials\r
+ *      provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ */\r
+package gr.grnet.pithos.web.client;\r
+\r
+import gr.grnet.pithos.web.client.foldertree.Resource;\r
+import gr.grnet.pithos.web.client.grouptree.Group;\r
+import gr.grnet.pithos.web.client.rest.PostRequest;\r
+import gr.grnet.pithos.web.client.rest.RestException;\r
+\r
+import com.google.gwt.core.client.GWT;\r
+import com.google.gwt.core.client.Scheduler;\r
+import com.google.gwt.dom.client.NativeEvent;\r
+import com.google.gwt.event.dom.client.ClickEvent;\r
+import com.google.gwt.event.dom.client.ClickHandler;\r
+import com.google.gwt.event.dom.client.KeyCodes;\r
+import com.google.gwt.event.dom.client.KeyDownEvent;\r
+import com.google.gwt.http.client.Response;\r
+import com.google.gwt.http.client.URL;\r
+import com.google.gwt.user.client.Event.NativePreviewEvent;\r
+import com.google.gwt.user.client.ui.Anchor;\r
+import com.google.gwt.user.client.ui.Button;\r
+import com.google.gwt.user.client.ui.DialogBox;\r
+import com.google.gwt.user.client.ui.FlexTable;\r
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
+import com.google.gwt.user.client.ui.TextBox;\r
+import com.google.gwt.user.client.ui.VerticalPanel;\r
+\r
+/**\r
+ * The 'Folder properties' dialog box implementation.\r
+ */\r
+public class AddUserDialog extends DialogBox {\r
+\r
+    protected Pithos app;\r
+\r
+    Group group;\r
+       /**\r
+        * The widget that holds the folderName of the folder.\r
+        */\r
+       TextBox userName = new TextBox();\r
+\r
+       final VerticalPanel inner;\r
+\r
+       /**\r
+        * The widget's constructor.\r
+        */\r
+       public AddUserDialog(final Pithos app, Group _group) {\r
+        this.app = app;\r
+        this.group = _group;\r
+        \r
+               Anchor close = new Anchor("close");\r
+               close.addStyleName("close");\r
+               close.addClickHandler(new ClickHandler() {\r
+                       \r
+                       @Override\r
+                       public void onClick(ClickEvent event) {\r
+                               hide();\r
+                       }\r
+               });\r
+\r
+               setAnimationEnabled(true);\r
+               setGlassEnabled(true);\r
+               setStyleName("pithos-DialogBox");\r
+\r
+               // Enable IE selection for the dialog (must disable it upon closing it)\r
+               Pithos.enableIESelection();\r
+\r
+               // Use this opportunity to set the dialog's caption.\r
+               setText("Add user");\r
+\r
+               // Outer contains inner and buttons\r
+               VerticalPanel outer = new VerticalPanel();\r
+               outer.add(close);\r
+               // Inner contains generalPanel and permPanel\r
+               inner = new VerticalPanel();\r
+               inner.addStyleName("inner");\r
+\r
+               VerticalPanel generalPanel = new VerticalPanel();\r
+        FlexTable generalTable = new FlexTable();\r
+        generalTable.setText(0, 0, "Username");\r
+\r
+        generalTable.setWidget(0, 1, userName);\r
+\r
+        generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");\r
+        generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");\r
+        generalTable.setCellSpacing(4);\r
+        generalPanel.add(generalTable);\r
+        inner.add(generalPanel);\r
+\r
+        outer.add(inner);\r
+\r
+               // Create the 'Create/Update' button, along with a listener that hides the dialog\r
+               // when the button is clicked and quits the application.\r
+               String okLabel = "Create";\r
+               final Button ok = new Button(okLabel, new ClickHandler() {\r
+                       @Override\r
+                       public void onClick(ClickEvent event) {\r
+                               addUser();\r
+                               closeDialog();\r
+                       }\r
+               });\r
+               ok.addStyleName("button");\r
+               outer.add(ok);\r
+        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
+\r
+        setWidget(outer);\r
+       }\r
+\r
+       @Override\r
+       public void center() {\r
+               super.center();\r
+               userName.setFocus(true);\r
+       }\r
+\r
+       @Override\r
+       protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
+               super.onPreviewNativeEvent(preview);\r
+\r
+               NativeEvent evt = preview.getNativeEvent();\r
+               if (evt.getType().equals(KeyDownEvent.getType().getName()))\r
+                       // Use the popup's key preview hooks to close the dialog when either\r
+                       // enter or escape is pressed.\r
+                       switch (evt.getKeyCode()) {\r
+                               case KeyCodes.KEY_ENTER:\r
+                                       addUser();\r
+                    closeDialog();\r
+                                       break;\r
+                               case KeyCodes.KEY_ESCAPE:\r
+                                       closeDialog();\r
+                                       break;\r
+                       }\r
+       }\r
+\r
+\r
+       /**\r
+        * Enables IE selection prevention and hides the dialog\r
+        * (we disable the prevention on creation of the dialog)\r
+        */\r
+       public void closeDialog() {\r
+               Pithos.preventIESelection();\r
+               hide();\r
+       }\r
+\r
+       /**\r
+        * Generate an RPC request to create a new folder.\r
+        */\r
+       void addUser() {\r
+               String name = userName.getText().trim();\r
+               if (name.length() == 0)\r
+                       return;\r
+       group.addMember(name);\r
+       String path = "?update=";\r
+       PostRequest updateGroup = new PostRequest(app.getApiPath(), app.getUsername(), path) {\r
+                       \r
+                       @Override\r
+                       public void onSuccess(Resource result) {\r
+                               app.updateGroupNode(group);\r
+                       }\r
+                       \r
+                       @Override\r
+                       public void onError(Throwable t) {\r
+                               GWT.log("", t);\r
+                               app.setError(t);\r
+                               if (t instanceof RestException) {\r
+                                       app.displayError("Unable to update group:" + ((RestException) t).getHttpStatusText());\r
+                               }\r
+                               else \r
+                                       app.displayError("System error updating group:" + t.getMessage());\r
+                       }\r
+\r
+                       @Override\r
+                       protected void onUnauthorized(Response response) {\r
+                               app.sessionExpired();\r
+                       }\r
+               };\r
+               updateGroup.setHeader("X-Auth-Token", app.getToken());\r
+               String groupMembers = "";\r
+               for (String u : group.getMembers())\r
+                       groupMembers += (URL.encodePathSegment(u) + ",");\r
+               updateGroup.setHeader("X-Account-Group-" + URL.encodePathSegment(group.getName()), groupMembers);\r
+               Scheduler.get().scheduleDeferred(updateGroup);\r
+       }\r
+}\r
index ff51899..27fb9bb 100644 (file)
@@ -60,7 +60,7 @@ public abstract class ConfirmationDialog extends DialogBox {
         * @param buttonLabel the label of the confirmation button
         */
        public ConfirmationDialog(String message, String buttonLabel) {
-               Anchor close = new Anchor();
+               Anchor close = new Anchor("close");
                close.addStyleName("close");
                close.addClickHandler(new ClickHandler() {
                        
index 4761b24..9fdbaf0 100644 (file)
@@ -62,7 +62,7 @@ public class CredentialsDialog extends DialogBox {
         * The widget constructor.
         */
        public CredentialsDialog(final Pithos app) {
-               Anchor close = new Anchor();
+               Anchor close = new Anchor("close");
                close.addStyleName("close");
                close.addClickHandler(new ClickHandler() {
                        
index 3b97710..75396d3 100644 (file)
@@ -78,7 +78,7 @@ public class DeleteFileDialog extends DialogBox {
        public DeleteFileDialog(Pithos _app, Images images, List<File> _files) {\r
         app = _app;\r
         files = _files;\r
-               Anchor close = new Anchor();\r
+               Anchor close = new Anchor("close");\r
                close.addStyleName("close");\r
                close.addClickHandler(new ClickHandler() {\r
                        \r
index d80806c..fc69ff1 100644 (file)
@@ -67,7 +67,7 @@ public class DeleteFolderDialog extends DialogBox {
         this.app = _app;\r
         this.folder = _folder;\r
 \r
-        Anchor close = new Anchor();\r
+        Anchor close = new Anchor("close");\r
                close.addStyleName("close");\r
                close.addClickHandler(new ClickHandler() {\r
                        \r
index ec7af4b..ab13e35 100644 (file)
@@ -68,7 +68,7 @@ public class FeedbackDialog extends DialogBox {
         */
        public FeedbackDialog(final Pithos app, final String appData) {
                // Set the dialog's caption.
-               Anchor close = new Anchor();
+               Anchor close = new Anchor("close");
                close.addStyleName("close");
                close.addClickHandler(new ClickHandler() {
                        
index 15528c2..0d5ddc1 100644 (file)
@@ -204,14 +204,15 @@ public class FileContextMenu extends PopupPanel {
                }
         }
         boolean isFolderTreeSelected = selectedTree.equals(app.getFolderTreeView());
+        boolean isMysharedSelected = selectedTree.equals(app.getMySharedTreeView());
         if (selectedFolder != null) {
                    if (!selectedFolder.isInTrash()) {
-                       if (canWrite && app.getClipboard().hasFiles()) {
+                       if (canWrite && app.getClipboard().hasFiles() && !isMysharedSelected) {
                                pasteItem = new MenuItem("<span>" + AbstractImagePrototype.create(images.paste()).getHTML() + "&nbsp;Paste</span>", true, new PasteCommand(app, this, selectedFolder));
                                contextMenu.addItem(pasteItem);
                        }
                
-                       if (canWrite) {
+                       if (canWrite && !isMysharedSelected) {
                                MenuItem upload = new MenuItem("<span>" + AbstractImagePrototype.create(images.fileUpdate()).getHTML() + "&nbsp;Upload</span>", true, new UploadFileCommand(app, this, selectedFolder));
                                contextMenu.addItem(upload);
                        }
@@ -231,8 +232,10 @@ public class FileContextMenu extends PopupPanel {
                                contextMenu.addItem(restore);
                    }
         }
-               copyItem = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.copy()).getHTML() + "&nbsp;Copy</span>", true, new CopyCommand(app, this, selectedFiles));
-        contextMenu.addItem(copyItem);
+        if (!isMysharedSelected) {
+                       copyItem = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.copy()).getHTML() + "&nbsp;Copy</span>", true, new CopyCommand(app, this, selectedFiles));
+               contextMenu.addItem(copyItem);
+        }
 
         if (isFolderTreeSelected) {
                        deleteItem = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.delete()).getHTML() + "&nbsp;Delete</span>", true, new DeleteCommand(app, this, selectedFiles, MessagePanel.images));
@@ -240,11 +243,12 @@ public class FileContextMenu extends PopupPanel {
         }
 
         if (selectedFolder != null && !selectedFolder.isInTrash()) {
-               if (isFolderTreeSelected && selectedFiles.size() == 1) {
+               if ((isFolderTreeSelected || isMysharedSelected) && selectedFiles.size() == 1) {
                        contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.viewText()).getHTML() + "&nbsp;Properties</span>", true, new PropertiesCommand(app, this, selectedFiles, PropertiesCommand.PROPERTIES)));
                        contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.sharing()).getHTML() + "&nbsp;Sharing</span>", true, new PropertiesCommand(app, this, selectedFiles, PropertiesCommand.PERMISSIONS)));
                        contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.internet()).getHTML() + "&nbsp;Publish</span>", true, new PropertiesCommand(app, this, selectedFiles, PropertiesCommand.PUBLISH)));
-                       contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.versions()).getHTML() + "&nbsp;Versions</span>", true, new PropertiesCommand(app, this, selectedFiles, PropertiesCommand.VERSIONS)));
+                       if (!isMysharedSelected)
+                               contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.versions()).getHTML() + "&nbsp;Versions</span>", true, new PropertiesCommand(app, this, selectedFiles, PropertiesCommand.VERSIONS)));
                }
 
         }
index 3e1a6f9..903b08f 100644 (file)
@@ -224,11 +224,13 @@ public class FileList extends Composite {
 
        private final MultiSelectionModel<File> selectionModel;
 
+       Column<File, String> pathColumn;
+
        protected final List<SortableHeader> allHeaders = new ArrayList<SortableHeader>();
 
        SortableHeader nameHeader;
 
-    FolderTreeView treeView;
+       SortableHeader pathHeader;
 
     protected Pithos app;
 
@@ -240,10 +242,9 @@ public class FileList extends Composite {
         *
         * @param _images
         */
-       public FileList(final Pithos _app, Images _images, FolderTreeView _treeView) {
+       public FileList(final Pithos _app, Images _images) {
         app = _app;
                images = _images;
-        this.treeView = _treeView;
 
         final CellTable.Resources resources = GWT.create(TableResources.class);
 
@@ -285,7 +286,16 @@ public class FileList extends Composite {
                        @Override
                        public SafeHtml getValue(File object) {
                                SafeHtmlBuilder sb = new SafeHtmlBuilder();
-                sb.append(Templates.INSTANCE.filenameSpan(object.getName()));
+                               if (!app.getSelectedTree().equals(app.mysharedTreeView)) {
+                                       sb.append(Templates.INSTANCE.filenameSpan(object.getName()));
+                               }
+                               else {
+                                       String name = object.getPath();
+                                       if (name.lastIndexOf("/") != -1) {
+                                               name = name.substring(name.lastIndexOf("/") + 1, name.length());
+                                       }
+                                       sb.append(Templates.INSTANCE.filenameSpan(name));
+                               }
                                if (object.getContentType() != null && (object.getContentType().endsWith("png") || object.getContentType().endsWith("gif") || object.getContentType().endsWith("jpeg"))) {
                                sb.appendHtmlConstant("&nbsp;")
                       .append(Templates.INSTANCE.viewLink(app.getApiPath() + object.getOwner() + object.getUri(), object.getName()));
@@ -303,6 +313,31 @@ public class FileList extends Composite {
 
                celltable.redrawHeaders();
                
+               pathColumn = new Column<File, String>(new TextCell()) {
+
+                       @Override
+                       public String getValue(File f) {
+                               String path;
+                               if (!app.getSelectedTree().equals(app.mysharedTreeView)) {
+                                       path = f.getParent().getPrefix();
+                                       if (path.length() == 0)
+                                               path = "/";
+                               }
+                               else {
+                                       path = f.getPath();
+                                       if (path.lastIndexOf("/") != -1)
+                                               path = path.substring(0, path.lastIndexOf("/"));
+                                       else
+                                               path = "/";
+                               }
+                               return path;
+                       }
+               };
+               pathHeader = new SortableHeader("Path", "path");
+               celltable.addColumn(pathColumn, pathHeader);
+               allHeaders.add(pathHeader);
+               pathHeader.setUpdater(new FileValueUpdater(pathHeader));
+               
         Column<File,String> aColumn = new Column<File,String>(new TextCell()) {
                        @Override
                        public String getValue(File object) {
@@ -338,7 +373,7 @@ public class FileList extends Composite {
             @Override
             public void onContextMenu(final ContextMenuEvent event) {
                final TreeView tree = app.getSelectedTree();
-               if (tree != null && (tree.equals(app.getFolderTreeView()) || tree.equals(app.getOtherSharedTreeView()))) {
+               if (tree != null) {
                        final int x = event.getNativeEvent().getClientX();
                        final int y = event.getNativeEvent().getClientY();
                        final Folder selectedFolder = app.getSelection();
@@ -473,6 +508,14 @@ public class FileList extends Composite {
         * Fill the file cache with data.
         */
        public void setFiles(final List<File> _files) {
+               if (!app.getSelectedTree().equals(app.mysharedTreeView)) {
+                       if (celltable.getColumnIndex(pathColumn) != -1)
+                               celltable.removeColumn(pathColumn);
+               }
+               else {
+                       if (celltable.getColumnIndex(pathColumn) == -1)
+                               celltable.insertColumn(2, pathColumn, pathHeader);
+               }
                files = new ArrayList<File>();
        for (File fres : _files) {
                        files.add(fres);
index 5209536..d4c94af 100644 (file)
@@ -88,7 +88,7 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                @Source("gr/grnet/pithos/resources/groups22.png")\r
                ImageResource permGroup();\r
 \r
-               @Source("gr/grnet/pithos/resources/editdelete.png")\r
+               @Source("gr/grnet/pithos/resources/delete.gif")\r
                ImageResource delete();\r
        }\r
 \r
@@ -173,9 +173,24 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
         Button add = new Button("Add Group", new ClickHandler() {\r
             @Override\r
             public void onClick(ClickEvent event) {\r
-                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
-                dlg.center();\r
-                permList.updatePermissionTable();\r
+               if (app.getAccount().getGroups().isEmpty()) {\r
+                    new GroupCreateDialog(app, new Command() {\r
+                                               \r
+                                               @Override\r
+                                               public void execute() {\r
+                                       if (app.getAccount().getGroups().isEmpty())\r
+                                               return;\r
+                                       PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                                       dlg.center();\r
+                                       permList.updatePermissionTable();\r
+                                               }\r
+                                       }).center();\r
+               }\r
+               else {\r
+                       PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                       dlg.center();\r
+                       permList.updatePermissionTable();\r
+               }\r
             }\r
         });\r
         add.addStyleName("button");\r
@@ -244,8 +259,9 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
         *\r
         */\r
        @Override\r
-       protected void accept() {\r
+       protected boolean accept() {\r
         updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", permList.getPermissions());\r
+        return true;\r
        }\r
 \r
        protected void updateMetaData(String api, String owner, final String path, final Map<String, Boolean[]> newPermissions) {\r
@@ -258,13 +274,16 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                                                @Override\r
                                                public void onSuccess(File _result) {\r
                                                        showLinkIfShared();\r
-                                   app.updateFolder(file.getParent(), true, new Command() {\r
-                                                               \r
-                                                               @Override\r
-                                                               public void execute() {\r
-                                                                       app.updateMySharedRoot();\r
-                                                               }\r
-                                                       }, true);\r
+                                                       if (!app.isMySharedSelected())\r
+                                           app.updateFolder(file.getParent(), true, new Command() {\r
+                                                                       \r
+                                                                       @Override\r
+                                                                       public void execute() {\r
+                                                                               app.updateMySharedRoot();\r
+                                                                       }\r
+                                                               }, true);\r
+                                                       else\r
+                                                               app.updateSharedFolder(file.getParent(), true);\r
                                                }\r
 \r
                                                @Override\r
@@ -322,7 +341,7 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
             updateFile.setHeader("X-Object-Sharing", permHeader);\r
             Scheduler.get().scheduleDeferred(updateFile);\r
         }\r
-        else\r
+        else if (!app.isMySharedSelected())\r
             app.updateFolder(file.getParent(), true, new Command() {\r
                                \r
                                @Override\r
@@ -331,6 +350,8 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                                                app.updateMySharedRoot();\r
                                }\r
                        }, true);\r
+        else\r
+               app.updateSharedFolder(file.getParent(), true);\r
     }\r
 \r
        @Override\r
index 336a5ee..06c9328 100644 (file)
@@ -112,8 +112,8 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                final Button ok = new Button("OK", new ClickHandler() {\r
                        @Override\r
                        public void onClick(ClickEvent event) {\r
-                               accept();\r
-                               closeDialog();\r
+                               if (accept())\r
+                                       closeDialog();\r
                        }\r
                });\r
                ok.addStyleName("button");\r
@@ -226,12 +226,15 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
         *\r
         */\r
        @Override\r
-       protected void accept() {\r
+       protected boolean accept() {\r
                String newFilename = null;\r
 \r
                if (!name.getText().trim().equals(file.getName())) {\r
                        newFilename = name.getText().trim();\r
+                       if (newFilename.length() == 0)\r
+                               newFilename = null;\r
                }\r
+               \r
 \r
         final Map<String, String> newMeta = new HashMap<String, String>();\r
         for (int row = 1; row < metaTable.getRowCount(); row++) {\r
@@ -239,6 +242,10 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                String value = ((TextBox) metaTable.getWidget(row, 1)).getText().trim();\r
                if (key.length() > 0 && value.length() > 0)\r
                        newMeta.put(key, value);\r
+               else if ((key.length() > 0 && value.length() == 0) || (key.length() == 0 && value.length() > 0)) {\r
+                       app.displayError("You have empty keys or values");\r
+                       return false;\r
+               }\r
         }\r
 \r
         if (newFilename != null) {\r
@@ -296,6 +303,7 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
         }\r
         else\r
             updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", newMeta);\r
+        return true;\r
        }\r
 \r
        protected void updateMetaData(String api, String owner, String path, Map<String, String> newMeta) {\r
@@ -303,13 +311,16 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
             PostRequest updateFile = new PostRequest(api, owner, path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
-                    app.updateFolder(file.getParent(), true, new Command() {\r
-                                               \r
-                                               @Override\r
-                                               public void execute() {\r
-                                                       app.updateMySharedRoot();\r
-                                               }\r
-                                       }, true);\r
+                       if (!app.isMySharedSelected())\r
+                           app.updateFolder(file.getParent(), true, new Command() {\r
+                                                       \r
+                                                       @Override\r
+                                                       public void execute() {\r
+                                                               app.updateMySharedRoot();\r
+                                                       }\r
+                                               }, true);\r
+                       else\r
+                               app.updateSharedFolder(file.getParent(), true);\r
                 }\r
 \r
                 @Override\r
@@ -335,7 +346,7 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
             \r
             Scheduler.get().scheduleDeferred(updateFile);\r
         }\r
-        else\r
+        else if (!app.isMySharedSelected())\r
             app.updateFolder(file.getParent(), true, new Command() {\r
                                \r
                                @Override\r
@@ -344,5 +355,7 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                                                app.updateMySharedRoot();\r
                                }\r
                        }, true);\r
+        else\r
+               app.updateSharedFolder(file.getParent(), true);\r
     }\r
 }\r
index ee96121..5fff7ef 100644 (file)
@@ -221,15 +221,17 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
     }\r
        /**\r
         * Accepts any change and updates the file\r
+        * @return \r
         *\r
         */\r
        @Override\r
-       protected void accept() {\r
+       protected boolean accept() {\r
         Boolean published = null;\r
                if (readForAll.getValue() != file.isPublished())\r
                        if (file.getOwner().equals(app.getUsername()))\r
                 published = readForAll.getValue();\r
         updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", published);\r
+        return true;\r
        }\r
 \r
        protected void updateMetaData(String api, String owner, final String path, final Boolean published) {\r
@@ -242,13 +244,16 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
                                                @Override\r
                                                public void onSuccess(File _result) {\r
                                                        showLinkIfPublished();\r
-                                   app.updateFolder(file.getParent(), true, new Command() {\r
-                                                               \r
-                                                               @Override\r
-                                                               public void execute() {\r
-                                                                       app.updateMySharedRoot();\r
-                                                               }\r
-                                                       }, true);\r
+                                                       if (!app.isMySharedSelected())\r
+                                           app.updateFolder(file.getParent(), true, new Command() {\r
+                                                                       \r
+                                                                       @Override\r
+                                                                       public void execute() {\r
+                                                                               app.updateMySharedRoot();\r
+                                                                       }\r
+                                                               }, true);\r
+                                                       else\r
+                                                               app.updateSharedFolder(file.getParent(), true);\r
                                                }\r
 \r
                                                @Override\r
@@ -283,7 +288,7 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
             updateFile.setHeader("X-Object-Public", published.toString());\r
             Scheduler.get().scheduleDeferred(updateFile);\r
         }\r
-        else\r
+        else if (!app.isMySharedSelected())\r
             app.updateFolder(file.getParent(), true, new Command() {\r
                                \r
                                @Override\r
@@ -292,6 +297,8 @@ public class FilePublishDialog extends AbstractPropertiesDialog {
                                                app.updateMySharedRoot();\r
                                }\r
                        }, true);\r
+        else\r
+               app.updateSharedFolder(file.getParent(), true);\r
     }\r
 \r
        @Override\r
index c2acca2..924c70f 100644 (file)
@@ -84,7 +84,7 @@ public class FileUploadDialog extends DialogBox {
         */
        public FileUploadDialog(Pithos _app) {
                app = _app;
-               Anchor close = new Anchor();
+               Anchor close = new Anchor("close");
                close.addStyleName("close");
                close.addClickHandler(new ClickHandler() {
                        
index e79007c..6229c4b 100644 (file)
@@ -185,10 +185,11 @@ public class FileVersionsDialog extends AbstractPropertiesDialog {
 \r
        /**\r
         * Accepts any change and updates the file\r
+        * @return \r
         *\r
         */\r
        @Override\r
-       protected void accept() {\r
+       protected boolean accept() {\r
         app.updateFolder(file.getParent(), true, new Command() {\r
                        \r
                        @Override\r
@@ -197,5 +198,7 @@ public class FileVersionsDialog extends AbstractPropertiesDialog {
                                        app.updateMySharedRoot();\r
                        }\r
                }, true);\r
+        \r
+        return true;\r
        }\r
 }\r
index a23cd29..72d31e8 100644 (file)
@@ -140,9 +140,11 @@ public class FilesPropertiesDialog extends AbstractPropertiesDialog {
 \r
        /**\r
         * Accepts any change and updates the file\r
+        * @return \r
         *\r
         */\r
        @Override\r
-       protected void accept() {\r
+       protected boolean accept() {\r
+               return true;\r
        }\r
 }\r
index e0dd76b..381f22e 100644 (file)
@@ -87,16 +87,17 @@ public class FolderContextMenu extends PopupPanel {
        boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
        boolean isFolderTreeSelected = selectedTree.equals(app.getFolderTreeView());
        boolean otherSharedTreeSelected = selectedTree.equals(app.getOtherSharedTreeView());
+       boolean mysharedTreeSelected = selectedTree.equals(app.getMySharedTreeView());
        
-       if (isFolderTreeSelected || otherSharedTreeSelected) {
-               MenuItem refresh = new MenuItem("<span id = 'folderContextMenu.refresh'>" + AbstractImagePrototype.create(images.refresh()).getHTML() + "&nbsp;Refresh</span>", true, new RefreshCommand(app, this, folder));
-               contextMenu.addItem(refresh);
-       }
+       MenuItem refresh = new MenuItem("<span id = 'folderContextMenu.refresh'>" + AbstractImagePrototype.create(images.refresh()).getHTML() + "&nbsp;Refresh</span>", true, new RefreshCommand(app, this, folder));
+        contextMenu.addItem(refresh);
 
         if (!folder.isInTrash()) {
                if (canWrite) {
-                       MenuItem newFolder = new MenuItem("<span id = 'folderContextMenu.newFolder'>" + AbstractImagePrototype.create(newImages.folderNew()).getHTML() + "&nbsp;New Folder</span>", true, new NewFolderCommand(app, this, folder));
-                       contextMenu.addItem(newFolder);
+                       if (!mysharedTreeSelected) {
+                               MenuItem newFolder = new MenuItem("<span id = 'folderContextMenu.newFolder'>" + AbstractImagePrototype.create(newImages.folderNew()).getHTML() + "&nbsp;New Folder</span>", true, new NewFolderCommand(app, this, folder));
+                               contextMenu.addItem(newFolder);
+                       }
 
                        if (isFolderTreeSelected && !folder.isContainer()) {
                            MenuItem cut = new MenuItem("<span id = 'folderContextMenu.cut'>" + AbstractImagePrototype.create(newImages.cut()).getHTML() + "&nbsp;Cut</span>", true, new CutCommand(app, this, folder));
@@ -110,7 +111,7 @@ public class FolderContextMenu extends PopupPanel {
                }
        
                if (canWrite) {
-                       if (!app.getClipboard().isEmpty()) {
+                       if (!app.getClipboard().isEmpty() && !mysharedTreeSelected) {
                                Object item = app.getClipboard().getItem();
                                boolean showPaste = true;
                                if (item instanceof Folder) {
index 47bd080..de6877f 100644 (file)
@@ -34,6 +34,7 @@
  */\r
 package gr.grnet.pithos.web.client;\r
 \r
+import gr.grnet.pithos.web.client.commands.CreateGroupCommand;\r
 import gr.grnet.pithos.web.client.foldertree.File;\r
 import gr.grnet.pithos.web.client.foldertree.Folder;\r
 import gr.grnet.pithos.web.client.foldertree.Resource;\r
@@ -86,7 +87,7 @@ public class FolderPermissionsDialog extends DialogBox {
         */\r
        public FolderPermissionsDialog(final Pithos app, Folder selected) {\r
         this.app = app;\r
-               Anchor close = new Anchor();\r
+               Anchor close = new Anchor("close");\r
                close.addStyleName("close");\r
                close.addClickHandler(new ClickHandler() {\r
                        \r
@@ -137,8 +138,22 @@ public class FolderPermissionsDialog extends DialogBox {
         Button add = new Button("Add Group", new ClickHandler() {\r
             @Override\r
             public void onClick(ClickEvent event) {\r
-                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
-                dlg.center();\r
+               if (app.getAccount().getGroups().isEmpty()) {\r
+                    new GroupCreateDialog(app, new Command() {\r
+                                               \r
+                                               @Override\r
+                                               public void execute() {\r
+                                       if (app.getAccount().getGroups().isEmpty())\r
+                                               return;\r
+                                       PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                                       dlg.center();\r
+                                               }\r
+                                       }).center();\r
+               }\r
+               else {\r
+                       PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                       dlg.center();\r
+               }\r
             }\r
         });\r
         add.addStyleName("button");\r
index aa5116d..d784cc9 100644 (file)
@@ -91,7 +91,7 @@ public class FolderPropertiesDialog extends DialogBox {
         */\r
        public FolderPropertiesDialog(final Pithos app, boolean _create,  Folder selected) {\r
         this.app = app;\r
-               Anchor close = new Anchor();\r
+               Anchor close = new Anchor("close");\r
                close.addStyleName("close");\r
                close.addClickHandler(new ClickHandler() {\r
                        \r
@@ -144,8 +144,11 @@ public class FolderPropertiesDialog extends DialogBox {
         if (create)\r
             generalTable.setText(1, 1, folder.getName());\r
         else\r
-            generalTable.setText(1, 1, folder.getPrefix());\r
-        generalTable.setText(2, 1, "");\r
+            generalTable.setText(1, 1, folder.getParent().getName());\r
+        if (create)\r
+               generalTable.setText(2, 1, app.getUsername());\r
+        else\r
+               generalTable.setText(2, 1, folder.getOwner());\r
         DateTimeFormat formatter = DateTimeFormat.getFormat("d/M/yyyy h:mm a");\r
         if(folder.getLastModified() != null)\r
             generalTable.setText(3, 1, formatter.format(folder.getLastModified()));\r
@@ -239,6 +242,8 @@ public class FolderPropertiesDialog extends DialogBox {
         */\r
        private void createFolder() {\r
                String name = folderName.getText().trim();\r
+               if (name.length() == 0)\r
+                       return;\r
         String path = folder.getUri() + "/" + name;\r
         PutRequest createFolder = new PutRequest(app.getApiPath(), folder.getOwner(), path) {\r
             @Override\r
@@ -290,6 +295,8 @@ public class FolderPropertiesDialog extends DialogBox {
 \r
        private void updateFolder() {\r
         final String newName = folderName.getText().trim();\r
+        if (newName.length() == 0)\r
+               return;\r
         if (!folder.isContainer() && !folder.getName().equals(newName)) {\r
             final String path = folder.getParent().getUri() + "/" + newName;\r
             PutRequest newFolder = new PutRequest(app.getApiPath(), folder.getParent().getOwner(), path) {\r
diff --git a/src/gr/grnet/pithos/web/client/GroupCreateDialog.java b/src/gr/grnet/pithos/web/client/GroupCreateDialog.java
new file mode 100644 (file)
index 0000000..4219e24
--- /dev/null
@@ -0,0 +1,185 @@
+/*\r
+ * Copyright 2011-2012 GRNET S.A. All rights reserved.\r
+ *\r
+ * Redistribution and use in source and binary forms, with or\r
+ * without modification, are permitted provided that the following\r
+ * conditions are met:\r
+ *\r
+ *   1. Redistributions of source code must retain the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer.\r
+ *\r
+ *   2. Redistributions in binary form must reproduce the above\r
+ *      copyright notice, this list of conditions and the following\r
+ *      disclaimer in the documentation and/or other materials\r
+ *      provided with the distribution.\r
+ *\r
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS\r
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\r
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR\r
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\r
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF\r
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\r
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\r
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN\r
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\r
+ * POSSIBILITY OF SUCH DAMAGE.\r
+ *\r
+ * The views and conclusions contained in the software and\r
+ * documentation are those of the authors and should not be\r
+ * interpreted as representing official policies, either expressed\r
+ * or implied, of GRNET S.A.\r
+ */\r
+package gr.grnet.pithos.web.client;\r
+\r
+import gr.grnet.pithos.web.client.foldertree.Folder;\r
+\r
+import com.google.gwt.dom.client.NativeEvent;\r
+import com.google.gwt.event.dom.client.ClickEvent;\r
+import com.google.gwt.event.dom.client.ClickHandler;\r
+import com.google.gwt.event.dom.client.KeyCodes;\r
+import com.google.gwt.event.dom.client.KeyDownEvent;\r
+import com.google.gwt.user.client.Command;\r
+import com.google.gwt.user.client.Event.NativePreviewEvent;\r
+import com.google.gwt.user.client.ui.Anchor;\r
+import com.google.gwt.user.client.ui.Button;\r
+import com.google.gwt.user.client.ui.DialogBox;\r
+import com.google.gwt.user.client.ui.FlexTable;\r
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
+import com.google.gwt.user.client.ui.TextBox;\r
+import com.google.gwt.user.client.ui.VerticalPanel;\r
+\r
+/**\r
+ * The 'Folder properties' dialog box implementation.\r
+ */\r
+public class GroupCreateDialog extends DialogBox {\r
+\r
+    protected Pithos app;\r
+\r
+    private Command callback;\r
+    \r
+       /**\r
+        * The widget that holds the folderName of the folder.\r
+        */\r
+       TextBox groupName = new TextBox();\r
+\r
+       final VerticalPanel inner;\r
+\r
+       public GroupCreateDialog(final Pithos app) {\r
+               this(app, null);\r
+       }\r
+       \r
+       /**\r
+        * The widget's constructor.\r
+        */\r
+       public GroupCreateDialog(final Pithos app, Command callback) {\r
+        this.app = app;\r
+        this.callback = callback;\r
+        \r
+               Anchor close = new Anchor("close");\r
+               close.addStyleName("close");\r
+               close.addClickHandler(new ClickHandler() {\r
+                       \r
+                       @Override\r
+                       public void onClick(ClickEvent event) {\r
+                               hide();\r
+                       }\r
+               });\r
+\r
+               setAnimationEnabled(true);\r
+               setGlassEnabled(true);\r
+               setStyleName("pithos-DialogBox");\r
+\r
+               // Enable IE selection for the dialog (must disable it upon closing it)\r
+               Pithos.enableIESelection();\r
+\r
+               // Use this opportunity to set the dialog's caption.\r
+               setText("Create group");\r
+\r
+               // Outer contains inner and buttons\r
+               VerticalPanel outer = new VerticalPanel();\r
+               outer.add(close);\r
+               // Inner contains generalPanel and permPanel\r
+               inner = new VerticalPanel();\r
+               inner.addStyleName("inner");\r
+\r
+               VerticalPanel generalPanel = new VerticalPanel();\r
+        FlexTable generalTable = new FlexTable();\r
+        generalTable.setText(0, 0, "Name");\r
+\r
+        generalTable.setWidget(0, 1, groupName);\r
+\r
+        generalTable.getFlexCellFormatter().setStyleName(0, 0, "props-labels");\r
+        generalTable.getFlexCellFormatter().setStyleName(0, 1, "props-values");\r
+        generalTable.setCellSpacing(4);\r
+        generalPanel.add(generalTable);\r
+        inner.add(generalPanel);\r
+\r
+        outer.add(inner);\r
+\r
+               // Create the 'Create/Update' button, along with a listener that hides the dialog\r
+               // when the button is clicked and quits the application.\r
+               String okLabel = "Create";\r
+               final Button ok = new Button(okLabel, new ClickHandler() {\r
+                       @Override\r
+                       public void onClick(ClickEvent event) {\r
+                               createGroup();\r
+                               closeDialog();\r
+                       }\r
+               });\r
+               ok.addStyleName("button");\r
+               outer.add(ok);\r
+        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
+\r
+        setWidget(outer);\r
+       }\r
+\r
+       @Override\r
+       public void center() {\r
+               super.center();\r
+               groupName.setFocus(true);\r
+       }\r
+\r
+       @Override\r
+       protected void onPreviewNativeEvent(NativePreviewEvent preview) {\r
+               super.onPreviewNativeEvent(preview);\r
+\r
+               NativeEvent evt = preview.getNativeEvent();\r
+               if (evt.getType().equals(KeyDownEvent.getType().getName()))\r
+                       // Use the popup's key preview hooks to close the dialog when either\r
+                       // enter or escape is pressed.\r
+                       switch (evt.getKeyCode()) {\r
+                               case KeyCodes.KEY_ENTER:\r
+                                       createGroup();\r
+                    closeDialog();\r
+                                       break;\r
+                               case KeyCodes.KEY_ESCAPE:\r
+                                       closeDialog();\r
+                                       break;\r
+                       }\r
+       }\r
+\r
+\r
+       /**\r
+        * Enables IE selection prevention and hides the dialog\r
+        * (we disable the prevention on creation of the dialog)\r
+        */\r
+       public void closeDialog() {\r
+               Pithos.preventIESelection();\r
+               hide();\r
+               if (callback != null)\r
+                       callback.execute();\r
+       }\r
+\r
+       /**\r
+        * Generate an RPC request to create a new folder.\r
+        */\r
+       void createGroup() {\r
+               String name = groupName.getText().trim();\r
+               if (name.length() == 0)\r
+                       return;\r
+               app.addGroup(name);\r
+       }\r
+}\r
index 5c733ba..55aaec6 100644 (file)
@@ -75,7 +75,7 @@ public class PermissionsAddDialog extends DialogBox {
                userAdd = _userAdd;
                permList = _permList;
 
-               Anchor close = new Anchor();
+               Anchor close = new Anchor("close");
                close.addStyleName("close");
                close.addClickHandler(new ClickHandler() {
                        
@@ -140,13 +140,17 @@ public class PermissionsAddDialog extends DialogBox {
         String selected = null;
                if (userAdd) {
                        selected = userBox.getText();
-               } else {
+               } else if (groupBox.getSelectedIndex() > -1) {
                        String groupName = groupBox.getValue(groupBox.getSelectedIndex());
-            selected = app.getUsername() + ":" + groupName;
+                       selected = app.getUsername() + ":" + groupName;
                }
         if (permList.getPermissions().get(selected) != null) {
             return;
         }
+        if (selected == null || selected.length() == 0 || selected.equals(app.getUsername() + ":")) {
+               app.displayError("You have to select o username or group");
+               return;
+        }
                boolean readValue = read.getValue();
                boolean writeValue = write.getValue();
 
index 1345efb..c7e58d2 100644 (file)
@@ -174,6 +174,7 @@ public class PermissionsList extends Composite {
                                changePermissionsCallback.execute();
                     }
                 });
+                removeButton.setTitle("Remove");
                 permTable.setWidget(i, 3, removeButton);
                 permTable.getFlexCellFormatter().setHorizontalAlignment(i, 3, HasHorizontalAlignment.ALIGN_CENTER);
             }
index 522e111..0da97e6 100644 (file)
@@ -238,7 +238,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
     OtherSharedTreeView otherSharedTreeView = null;
 
     GroupTreeViewModel groupTreeViewModel;
-    private GroupTreeView groupTreeView;
+    GroupTreeView groupTreeView;
 
     TreeView selectedTree;
     protected AccountResource account;
@@ -251,12 +251,6 @@ public class Pithos implements EntryPoint, ResizeHandler {
     
     Button upload;
     
-    private HTML usedBytes;
-    
-    private HTML totalBytes;
-    
-    private HTML usedPercent;
-    
     private HTML numOfFiles;
     
     private Toolbar toolbar;
@@ -362,43 +356,18 @@ public class Pithos implements EntryPoint, ResizeHandler {
         folderTreeView = new FolderTreeView(folderTreeViewModel);
         treeViews.add(folderTreeView);
         
-        fileList = new FileList(this, images, folderTreeView);
+        fileList = new FileList(this, images);
         inner.add(fileList);
 
-        groupTreeViewModel = new GroupTreeViewModel(this);
-        groupTreeView = new GroupTreeView(groupTreeViewModel);
-        treeViews.add(groupTreeView);
-        
         trees = new VerticalPanel();
         trees.setWidth("100%");
-
         
-        HorizontalPanel treeHeader = new HorizontalPanel();
-        treeHeader.addStyleName("pithos-treeHeader");
-        treeHeader.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_CENTER);
-        treeHeader.setVerticalAlignment(HasVerticalAlignment.ALIGN_MIDDLE);
-        HorizontalPanel statistics = new HorizontalPanel();
-        statistics.addStyleName("pithos-statistics");
-        statistics.add(new HTML("Used:&nbsp;"));
-        usedBytes = new HTML();
-        statistics.add(usedBytes);
-        statistics.add(new HTML("&nbsp;of&nbsp;"));
-        totalBytes = new HTML();
-        statistics.add(totalBytes);
-        statistics.add(new HTML("&nbsp;("));
-        usedPercent = new HTML();
-        statistics.add(usedPercent);
-        statistics.add(new HTML(")"));
-        treeHeader.add(statistics);
-        treeHeader.setCellHorizontalAlignment(statistics, HasHorizontalAlignment.ALIGN_LEFT);
-        trees.add(treeHeader);
-
         trees.add(folderTreeView);
-        trees.add(groupTreeView);
+        
         // Add the left and right panels to the split panel.
         splitPanel.setLeftWidget(trees);
         splitPanel.setRightWidget(inner);
-        splitPanel.setSplitPosition("35%");
+        splitPanel.setSplitPosition("219px");
         splitPanel.setSize("100%", "100%");
         splitPanel.addStyleName("pithos-splitPanel");
         splitPanel.setWidth(contentWidth);
@@ -457,8 +426,17 @@ public class Pithos implements EntryPoint, ResizeHandler {
                                                    createMySharedTree();
                                                                }
                                                        });
-                                   groupTreeViewModel.initialize();
-                                   showStatistics();
+
+                                   HorizontalPanel separator = new HorizontalPanel();
+                                   separator.addStyleName("pithos-statisticsSeparator");
+                                   separator.add(new HTML(""));
+                                   trees.add(separator);
+
+                                   groupTreeViewModel = new GroupTreeViewModel(Pithos.this);
+                                   groupTreeView = new GroupTreeView(groupTreeViewModel);
+                                   treeViews.add(groupTreeView);
+                                   trees.add(groupTreeView);
+                                   folderTreeView.showStatistics(account);
                                }
                                        }
                                });
@@ -526,31 +504,25 @@ public class Pithos implements EntryPoint, ResizeHandler {
         * Parse and store the user credentials to the appropriate fields.
         */
        private boolean parseUserCredentials() {
-        username = Window.Location.getParameter("user");
-        token = Window.Location.getParameter("token");
         Configuration conf = (Configuration) GWT.create(Configuration.class);
                Dictionary otherProperties = Dictionary.getDictionary("otherProperties");
-        if (username == null || username.length() == 0 || token == null || token.length() == 0) {
-            String cookie = otherProperties.get("authCookie");
-            String auth = Cookies.getCookie(cookie);
-            if (auth == null) {
-                authenticateUser();
-                return false;
-            }
-            if (auth.startsWith("\""))
-               auth = auth.substring(1);
-            if (auth.endsWith("\""))
-               auth = auth.substring(0, auth.length() - 1);
-                       String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
-                       if (authSplit.length != 2) {
-                           authenticateUser();
-                           return false;
-                       }
-                       username = authSplit[0];
-                       token = authSplit[1];
+        String cookie = otherProperties.get("authCookie");
+        String auth = Cookies.getCookie(cookie);
+        if (auth == null) {
+            authenticateUser();
+            return false;
         }
-        else
-               Cookies.setCookie(otherProperties.get("authCookie"), username + conf.cookieSeparator() + token, null, "", "/", false);
+        if (auth.startsWith("\""))
+               auth = auth.substring(1);
+        if (auth.endsWith("\""))
+               auth = auth.substring(0, auth.length() - 1);
+               String[] authSplit = auth.split("\\" + conf.cookieSeparator(), 2);
+               if (authSplit.length != 2) {
+                   authenticateUser();
+                   return false;
+               }
+               username = authSplit[0];
+               token = authSplit[1];
 
         String gotoUrl = Window.Location.getParameter("goto");
                if (gotoUrl != null && gotoUrl.length() > 0) {
@@ -603,7 +575,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
 
                        @Override
                        public void onSuccess(AccountResource _result) {
-                               showStatistics();
+                               folderTreeView.showStatistics(account);
                        }
 
                        @Override
@@ -625,13 +597,6 @@ public class Pithos implements EntryPoint, ResizeHandler {
                Scheduler.get().scheduleDeferred(headAccount);
        }
 
-       protected void showStatistics() {
-       usedBytes.setHTML(String.valueOf(account.getFileSizeAsString()));
-       totalBytes.setHTML(String.valueOf(account.getQuotaAsString()));
-       NumberFormat nf = NumberFormat.getPercentFormat();
-       usedPercent.setHTML(nf.format(account.getUsedPercentage()));
-       }
-
        protected void createHomeContainer(final AccountResource _account, final Command callback) {
         String path = "/" + Pithos.HOME_CONTAINER;
         PutRequest createPithos = new PutRequest(getApiPath(), getUsername(), path) {
@@ -1100,7 +1065,9 @@ public class Pithos implements EntryPoint, ResizeHandler {
        }
 
        public Folder getSelection() {
-               return selectedTree.getSelection();
+               if (selectedTree != null)
+                       return selectedTree.getSelection();
+               return null;
        }
 
        public void showFolderStatistics(int folderFileCount) {
@@ -1179,7 +1146,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
                        @Override
                        public void execute() {
                            otherSharedTreeView = new OtherSharedTreeView(otherSharedTreeViewModel);
-                               trees.insert(otherSharedTreeView, 3);
+                               trees.insert(otherSharedTreeView, 1);
                                treeViews.add(otherSharedTreeView);
                        }
                });
@@ -1313,4 +1280,8 @@ public class Pithos implements EntryPoint, ResizeHandler {
                headFile.setHeader("X-Auth-Token", getToken());
                Scheduler.get().scheduleDeferred(headFile);
        }
+
+       public boolean isMySharedSelected() {
+               return getSelectedTree().equals(getMySharedTreeView());
+       }
 }
index 539f2cf..4cf7439 100644 (file)
@@ -23,7 +23,7 @@
        cursor: pointer;
        color: white;
        background-color: #74aec9;
-       height: 25px;
+       height: 28px;
        text-shadow: none;
        font-size: 13px;
        font-weight: normal;
index 09ca179..2e1e640 100644 (file)
@@ -75,8 +75,9 @@
 
 .cellTreeSelectedItem {
   color: #d45500;
-  background-color: #BCD7E3;
-  height: auto;
+  background-color: #A1C8DA;
+/*   background-color: #BCD7E3;
+ */  height: auto;
   overflow: visible;
 }
 
diff --git a/src/gr/grnet/pithos/web/client/PithosDisclosurePanel.css b/src/gr/grnet/pithos/web/client/PithosDisclosurePanel.css
new file mode 100644 (file)
index 0000000..fd4e044
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+.disclosurePanel {
+       width: 100%;
+       margin-bottom: 5px;
+}
+
+.header {
+       background-color: #74aec9;
+       height: 28px;
+    width: 100%;
+    padding-left: 6px;
+}
+
+.arrow { 
+       padding-right: 2px;
+}
+
+.content {
+       width: 100%;
+}
diff --git a/src/gr/grnet/pithos/web/client/PithosDisclosurePanel.java b/src/gr/grnet/pithos/web/client/PithosDisclosurePanel.java
new file mode 100644 (file)
index 0000000..cff566d
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+
+package gr.grnet.pithos.web.client;
+
+import com.google.gwt.event.logical.shared.CloseEvent;
+import com.google.gwt.event.logical.shared.CloseHandler;
+import com.google.gwt.event.logical.shared.OpenEvent;
+import com.google.gwt.event.logical.shared.OpenHandler;
+import com.google.gwt.resources.client.ClientBundle;
+import com.google.gwt.resources.client.CssResource;
+import com.google.gwt.resources.client.ImageResource;
+import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.HasVerticalAlignment;
+import com.google.gwt.user.client.ui.HorizontalPanel;
+import com.google.gwt.user.client.ui.Image;
+import com.google.gwt.user.client.ui.Widget;
+
+public class PithosDisclosurePanel extends Composite {
+
+       public interface Style extends CssResource {
+               String disclosurePanel();
+               
+               String header();
+               
+               String arrow();
+               
+               String content();
+       }
+       
+       public interface Resources extends ClientBundle {
+               @Source("PithosDisclosurePanel.css")
+               Style pithosDisclosurePanelCss();
+               
+               @Source("upArrow.png")
+               ImageResource icon();
+               
+               @Source("upArrow.png")
+               ImageResource open();
+               
+               @Source("downArrow.png")
+               ImageResource closed();
+       }
+       
+       DisclosurePanel panel;
+       
+       Resources resources;
+       
+       public PithosDisclosurePanel(final Resources _resources, final String title, boolean open) {
+               resources = _resources;
+               resources.pithosDisclosurePanelCss().ensureInjected();
+               panel = new DisclosurePanel();
+               panel.addStyleName(resources.pithosDisclosurePanelCss().disclosurePanel());
+               panel.setHeader(createHeader(resources, title, open));
+               panel.setOpen(open);
+               panel.setAnimationEnabled(true);
+               panel.addOpenHandler(new OpenHandler<DisclosurePanel>() {
+                       
+                       @Override
+                       public void onOpen(OpenEvent<DisclosurePanel> event) {
+                               panel.setHeader(createHeader(resources, title, true));
+                       }
+               });
+               panel.addCloseHandler(new CloseHandler<DisclosurePanel>() {
+                       
+                       @Override
+                       public void onClose(CloseEvent<DisclosurePanel> event) {
+                               panel.setHeader(createHeader(resources, title, false));
+                       }
+               });
+               
+               initWidget(panel);
+       }
+       
+       Widget createHeader(Resources resources, String title, boolean open) {
+               HorizontalPanel header = new HorizontalPanel();
+        
+               Image img = new Image(resources.icon());
+               header.add(img);
+               header.setCellVerticalAlignment(img, HasVerticalAlignment.ALIGN_MIDDLE);
+               header.setCellWidth(img, "32px");
+               HTML titleHtml = new HTML(title);
+               header.add(titleHtml);
+               header.setCellVerticalAlignment(titleHtml, HasVerticalAlignment.ALIGN_MIDDLE);
+               Image arrow = new Image(open ? resources.open() : resources.closed());
+               arrow.addStyleName(resources.pithosDisclosurePanelCss().arrow());
+               header.add(arrow);
+               header.setCellHorizontalAlignment(arrow, HasHorizontalAlignment.ALIGN_RIGHT);
+               header.setCellVerticalAlignment(arrow, HasVerticalAlignment.ALIGN_MIDDLE);
+               
+               header.addStyleName(resources.pithosDisclosurePanelCss().header());
+               return header;
+       }
+       
+       public void setContent(Widget widget) {
+               panel.setContent(widget);
+               panel.getContent().removeStyleName("content");
+               panel.getContent().addStyleName(resources.pithosDisclosurePanelCss().content());
+       }
+}
index 35ffe88..f8d084b 100644 (file)
@@ -121,16 +121,22 @@ public class Toolbar extends Composite {
                        boolean otherSharedTreeSelected = app.getSelectedTree().equals(app.getOtherSharedTreeView());
                        Folder folder = app.getSelectedTree().getSelection();
                        
-                       if (folder != null && (isFolderTreeSelected || otherSharedTreeSelected))
-                               app.updateFolder(folder, true, new Command() {
+                       if (folder != null) {
+                               if (!app.isMySharedSelected()) {
+                                       app.updateFolder(folder, true, new Command() {
+                                               
+                                               @Override
+                                               public void execute() {
+                                                       app.updateStatistics();
+                                               }
+                                       }, true);
+                               }
+                               else
+                                       app.updateSharedFolder(folder, true);
                                        
-                                       @Override
-                                       public void execute() {
-                                               app.updateStatistics();
-                                       }
-                               }, true);
+                       }
                        }
-               });
+        });
         toolbar.add(refreshButton);
 
         toolsButton = new Anchor("<span class='ico'></span><span class='title'>More...</span>", true);
@@ -166,14 +172,13 @@ public class Toolbar extends Composite {
                                        boolean isFolderTreeSelected = app.getSelectedTree().equals(app.getFolderTreeView());
                                        boolean otherSharedTreeSelected = app.getSelectedTree().equals(app.getOtherSharedTreeView());
                                        
-                                       if (isFolderTreeSelected || otherSharedTreeSelected)
-                                               refreshButton.setVisible(true);
-                                       else
-                                               refreshButton.setVisible(true);
+                                       refreshButton.setVisible(true);
                                        
                                        if (!folder.isInTrash() && canWrite) {
                                                if (isFolderTreeSelected || otherSharedTreeSelected)
                                                        newFolderButton.setVisible(true);
+                                               else
+                                                       newFolderButton.setVisible(false);
                                                if (isFolderTreeSelected && !folder.isContainer())
                                                        shareFolderButton.setVisible(true);
                                                else
index e51776e..3da9ed1 100644 (file)
@@ -100,6 +100,7 @@ public class ToolsMenu extends PopupPanel {
                Boolean[] permissions = folder.getPermissions().get(app.getUsername());
                boolean canWrite = folder.getOwner().equals(app.getUsername()) || (permissions!= null && permissions[1] != null && permissions[1]);
                boolean isFolderTreeSelected = selectedTree.equals(app.getFolderTreeView());
+               boolean isMysharedTreeSelected = app.isMySharedSelected();
                
                if (!folder.isInTrash()) {
                        if (canWrite) {
@@ -119,18 +120,20 @@ public class ToolsMenu extends PopupPanel {
                                }
                        }
        
-                       MenuItem copy = null;
-                       if (files != null && !files.isEmpty())
-                               copy = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.copy()).getHTML() + "&nbsp;Copy files</span>", true, new CopyCommand(app, this, files));
-                       else if (isFolderTreeSelected && !folder.isContainer())
-                               copy = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.copy()).getHTML() + "&nbsp;Copy folder</span>", true, new CopyCommand(app, this, folder));
-                       if (copy != null) {
-                               contextMenu.addItem(copy);
-                               empty = false;
+                       if (!isMysharedTreeSelected) {
+                               MenuItem copy = null;
+                               if (files != null && !files.isEmpty())
+                                       copy = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.copy()).getHTML() + "&nbsp;Copy files</span>", true, new CopyCommand(app, this, files));
+                               else if (isFolderTreeSelected && !folder.isContainer())
+                                       copy = new MenuItem("<span>" + AbstractImagePrototype.create(newImages.copy()).getHTML() + "&nbsp;Copy folder</span>", true, new CopyCommand(app, this, folder));
+                               if (copy != null) {
+                                       contextMenu.addItem(copy);
+                                       empty = false;
+                               }
                        }
                
                        if (canWrite) {
-                               if (!app.getClipboard().isEmpty()) {
+                               if (!isMysharedTreeSelected && !app.getClipboard().isEmpty()) {
                                        Object item = app.getClipboard().getItem();
                                        boolean showPaste = false;
                                        if (item instanceof List) {
@@ -174,12 +177,14 @@ public class ToolsMenu extends PopupPanel {
                                                contextMenu.addItem(delete);
                                                empty = false;
                                        }
-                               
+                                   }
+                                   if (isFolderTreeSelected || isMysharedTreeSelected) {
                                        if (files != null && files.size() == 1) {
                                                contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.viewText()).getHTML() + "&nbsp;File properties</span>", true, new PropertiesCommand(app, this, files, PropertiesCommand.PROPERTIES)));
                                                contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.group()).getHTML() + "&nbsp;Sharing</span>", true, new PropertiesCommand(app, this, files, PropertiesCommand.PERMISSIONS)));
                                                contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.internet()).getHTML() + "&nbsp;Publish</span>", true, new PropertiesCommand(app, this, files, PropertiesCommand.PUBLISH)));
-                                               contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.versions()).getHTML() + "&nbsp;Versions</span>", true, new PropertiesCommand(app, this, files, PropertiesCommand.VERSIONS)));
+                                               if (!isMysharedTreeSelected)
+                                                       contextMenu.addItem(new MenuItem("<span>" + AbstractImagePrototype.create(newImages.versions()).getHTML() + "&nbsp;Versions</span>", true, new PropertiesCommand(app, this, files, PropertiesCommand.VERSIONS)));
                                                empty = false;
                                        }
                                        else if (!folder.isContainer()) {
@@ -237,13 +242,11 @@ public class ToolsMenu extends PopupPanel {
                        contextMenu.addItem(deleteGroup);
                                empty = false;
                        }
-                       else {
-                       MenuItem createGroup = new MenuItem("<span>" + AbstractImagePrototype.create(images.group()).getHTML() + "&nbsp;Create Group</span>", true, new CreateGroupCommand(app, this));
-                       contextMenu.addItem(createGroup);
-                               empty = false;
-                       }
                }
         }
+        MenuItem createGroup = new MenuItem("<span>" + AbstractImagePrototype.create(images.group()).getHTML() + "&nbsp;Create Group</span>", true, new CreateGroupCommand(app, this));
+        contextMenu.addItem(createGroup);
+       empty = false;
                add(contextMenu);
        }
        
index 075fb5a..5fe90a8 100644 (file)
@@ -34,6 +34,7 @@
  */
 package gr.grnet.pithos.web.client.commands;
 
+import gr.grnet.pithos.web.client.AddUserDialog;
 import gr.grnet.pithos.web.client.Pithos;
 import gr.grnet.pithos.web.client.foldertree.Resource;
 import gr.grnet.pithos.web.client.grouptree.Group;
@@ -72,39 +73,7 @@ public class AddUserCommand implements Command {
        public void execute() {
         if (containerPanel != null)
                    containerPanel.hide();
-        String username = Window.prompt("Enter username:", "");
-        if (username != null && username.length() > 0) {
-               group.addMember(username);
-               String path = "?update=";
-               PostRequest updateGroup = new PostRequest(app.getApiPath(), app.getUsername(), path) {
-                               
-                               @Override
-                               public void onSuccess(Resource result) {
-                                       app.updateGroupNode(group);
-                               }
-                               
-                               @Override
-                               public void onError(Throwable t) {
-                                       GWT.log("", t);
-                                       app.setError(t);
-                                       if (t instanceof RestException) {
-                                               app.displayError("Unable to update group:" + ((RestException) t).getHttpStatusText());
-                                       }
-                                       else 
-                                               app.displayError("System error updating group:" + t.getMessage());
-                               }
-
-                               @Override
-                               protected void onUnauthorized(Response response) {
-                                       app.sessionExpired();
-                               }
-                       };
-                       updateGroup.setHeader("X-Auth-Token", app.getToken());
-                       String groupMembers = "";
-                       for (String u : group.getMembers())
-                               groupMembers += (URL.encodePathSegment(u) + ",");
-                       updateGroup.setHeader("X-Account-Group-" + URL.encodePathSegment(group.getName()), groupMembers);
-                       Scheduler.get().scheduleDeferred(updateGroup);
-        }
+        AddUserDialog dlg = new AddUserDialog(app, group);
+        dlg.center();
        }
 }
index aafb805..95dc5e6 100644 (file)
@@ -34,6 +34,7 @@
  */
 package gr.grnet.pithos.web.client.commands;
 
+import gr.grnet.pithos.web.client.GroupCreateDialog;
 import gr.grnet.pithos.web.client.Pithos;
 
 import com.google.gwt.user.client.Command;
@@ -61,9 +62,7 @@ public class CreateGroupCommand implements Command {
        public void execute() {
         if (containerPanel != null)
                    containerPanel.hide();
-        String groupname = Window.prompt("Enter group name:", "");
-        if (groupname != null && groupname.length() > 0) {
-               app.addGroup(groupname);
-        }
+        GroupCreateDialog dlg = new GroupCreateDialog(app);
+        dlg.center();
        }
 }
index a35f9a8..01f6acd 100644 (file)
@@ -62,12 +62,15 @@ public class RefreshCommand implements Command {
        public void execute() {
                if (containerPanel != null)
                        containerPanel.hide();
-               app.updateFolder(folder, true, new Command() {
-                       
-                       @Override
-                       public void execute() {
-                               app.updateStatistics();
-                       }
-               }, true);
+               if (app.getSelectedTree().equals(app.getMySharedTreeView()))
+                       app.updateSharedFolder(folder, true);
+               else
+                       app.updateFolder(folder, true, new Command() {
+                               
+                               @Override
+                               public void execute() {
+                                       app.updateStatistics();
+                               }
+                       }, true);
        }
 }
index 01a3215..83aeeb8 100644 (file)
@@ -63,8 +63,6 @@ public class File extends Resource {
 
     private String modifiedBy;
 
-    private Date versionTimestamp;
-
     private String path;
 
     private String owner;
@@ -108,10 +106,6 @@ public class File extends Resource {
         return version;
     }
 
-    public Date getVersionTimestamp() {
-        return versionTimestamp;
-    }
-
     public String getUri() {
         return "/" + container + "/" + path;
     }
@@ -157,11 +151,10 @@ public class File extends Resource {
         this.owner = _owner;
         hash = unmarshallString(o, "hash");
         bytes = unmarshallLong(o, "bytes");
-        version = unmarshallInt(o, "version");
+        version = unmarshallInt(o, "x_object_version");
         contentType = unmarshallString(o, "content_type");
         lastModified = unmarshallDate(o, "last_modified");
-        modifiedBy = unmarshallString(o, "modified_by");
-        versionTimestamp = unmarshallDate(o, "version_timestamp");
+        modifiedBy = unmarshallString(o, "x_object_modified_by");
         published = o.containsKey("x_object_public") ? true : false;
         publicUri = unmarshallString(o, "x_object_public");
         this.container = _container;
index 08d9e74..7062e9f 100644 (file)
 package gr.grnet.pithos.web.client.foldertree;
 
 import gr.grnet.pithos.web.client.FolderContextMenu;
+import gr.grnet.pithos.web.client.PithosDisclosurePanel;
 import gr.grnet.pithos.web.client.TreeView;
 
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.i18n.client.NumberFormat;
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.resources.client.ImageResource.ImageOptions;
 import com.google.gwt.resources.client.ImageResource.RepeatStyle;
@@ -49,7 +51,11 @@ import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSe
 import com.google.gwt.user.cellview.client.TreeNode;
 import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.HTML;
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;
+import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Tree;
+import com.google.gwt.user.client.ui.VerticalPanel;
 
 public class FolderTreeView extends Composite implements TreeView {
 
@@ -72,7 +78,7 @@ public class FolderTreeView extends Composite implements TreeView {
        }
        
     public void openFolder(Folder folder) {
-        TreeNode root = ((CellTree) getWidget()).getRootTreeNode();
+        TreeNode root = tree.getRootTreeNode();
         openFolder(root, folder);
     }
 
@@ -122,15 +128,12 @@ public class FolderTreeView extends Composite implements TreeView {
         @Source("gr/grnet/pithos/resources/home22.png")
         ImageResource home();
 
-        @Source("gr/grnet/pithos/resources/folder22.png")
+        @Source("gr/grnet/pithos/resources/2folder22.png")
         public ImageResource folderYellow();
 
         @Source("gr/grnet/pithos/resources/mimetypes/document.png")
         ImageResource document();
 
-        @Source("gr/grnet/pithos/resources/othersshared.png")
-        ImageResource othersShared();
-
         @Source("gr/grnet/pithos/resources/myshared22.png")
         ImageResource myShared();
 
@@ -153,20 +156,61 @@ public class FolderTreeView extends Composite implements TreeView {
         public SafeHtml imageSpan(String name);
     }
 
+    interface Resources extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Resources {
+               @Override
+               @Source("gr/grnet/pithos/resources/home22.png")
+       ImageResource icon();
+    }
+
     private FolderTreeViewModel model;
+    
+    private CellTree tree;
+    
+    private HTML usedBytes;
+    
+    private HTML totalBytes;
+    
+    private HTML usedPercent;
 
     public FolderTreeView(FolderTreeViewModel viewModel) {
         this.model = viewModel;
+
+        PithosDisclosurePanel panel = new PithosDisclosurePanel((Resources) GWT.create(Resources.class), "My Files", true);
+
+        VerticalPanel content = new VerticalPanel();
+        
         /*
          * Create the tree using the model. We use <code>null</code> as the default
          * value of the root node. The default value will be passed to
          * CustomTreeModel#getNodeInfo();
          */
         CellTree.Resources res = GWT.create(BasicResources.class);
-        CellTree tree = new CellTree(model, null, res);
+        tree = new CellTree(model, null, res);
         tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
-
-        initWidget(tree);
+        content.add(tree);
+
+        HorizontalPanel separator = new HorizontalPanel();
+        separator.addStyleName("pithos-statisticsSeparator");
+        separator.add(new HTML(""));
+        content.add(separator);
+
+        HorizontalPanel statistics = new HorizontalPanel();
+           statistics.addStyleName("pithos-statistics");
+           statistics.add(new HTML("Used:&nbsp;"));
+           usedBytes = new HTML();
+           statistics.add(usedBytes);
+           statistics.add(new HTML("&nbsp;of&nbsp;"));
+           totalBytes = new HTML();
+           statistics.add(totalBytes);
+           statistics.add(new HTML("&nbsp;("));
+           usedPercent = new HTML();
+           statistics.add(usedPercent);
+           statistics.add(new HTML(")"));
+           content.add(statistics);
+           content.setCellHorizontalAlignment(statistics, HasHorizontalAlignment.ALIGN_CENTER);
+
+        panel.setContent(content);
+        initWidget(panel);
     }
 
 
@@ -178,4 +222,11 @@ public class FolderTreeView extends Composite implements TreeView {
     public void updateFolder(Folder folder, boolean showfiles, Command callback, final boolean openParent) {
         model.updateFolder(folder, showfiles, callback, openParent);
     }
+    
+       public void showStatistics(AccountResource account) {
+       usedBytes.setHTML(String.valueOf(account.getFileSizeAsString()));
+       totalBytes.setHTML(String.valueOf(account.getQuotaAsString()));
+       NumberFormat nf = NumberFormat.getPercentFormat();
+       usedPercent.setHTML(nf.format(account.getUsedPercentage()));
+       }
 }
index 843f14f..5e4f348 100644 (file)
@@ -72,7 +72,7 @@ public class FolderTreeViewModel implements TreeViewModel {
             String html;
             SafeHtml name;
                if (folder.isHome()) {
-                       html = AbstractImagePrototype.create(FolderTreeView.images.home()).getHTML();
+                       html = AbstractImagePrototype.create(FolderTreeView.images.folderYellow()).getHTML();
                        name = Templates.INSTANCE.nameSpan("Pithos");
                }
                else if (folder.isTrash()) {
index e0cb5cf..b0d3bd7 100644 (file)
@@ -36,7 +36,9 @@
 package gr.grnet.pithos.web.client.grouptree;
 
 import gr.grnet.pithos.web.client.FolderContextMenu;
+import gr.grnet.pithos.web.client.PithosDisclosurePanel;
 import gr.grnet.pithos.web.client.TreeView;
+import gr.grnet.pithos.web.client.PithosDisclosurePanel.Style;
 import gr.grnet.pithos.web.client.foldertree.Folder;
 
 import com.google.gwt.core.client.GWT;
@@ -50,15 +52,17 @@ import com.google.gwt.user.cellview.client.CellTree;
 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
 import com.google.gwt.user.cellview.client.TreeNode;
 import com.google.gwt.user.client.ui.Composite;
+import com.google.gwt.user.client.ui.DisclosurePanel;
+import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Tree;
 
 public class GroupTreeView extends Composite implements TreeView {
 
     public void updateChildren(Group group) {
-        TreeNode root = ((CellTree) getWidget()).getRootTreeNode();
+        TreeNode root = tree.getRootTreeNode();
         if (group != null)
                updateChildren(root, group);
-        else {
+        else if (root.getChildCount() > 0) {
                root.setChildOpen(0, false, true);
                root.setChildOpen(0, true, true);
         }
@@ -118,28 +122,49 @@ public class GroupTreeView extends Composite implements TreeView {
     }
 
     static Images images = GWT.create(Images.class);
+    
+    interface Style extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Style {
+       @Override
+               String header();
+    }
+    interface Resources extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Resources {
+               @Override
+               @Source("PithosGroupDisclosurePanel.css")
+               Style pithosDisclosurePanelCss();
+
+               @Override
+               @Source("gr/grnet/pithos/resources/groups22.png")
+       ImageResource icon();
+    }
 
-    static interface Templates extends SafeHtmlTemplates {
+    public static interface Templates extends SafeHtmlTemplates {
         public Templates INSTANCE = GWT.create(Templates.class);
 
-        @Template("<span>{0}</span>")
+        @Template("<span style='margin-left:5px;'>{0}</span>")
         public SafeHtml nameSpan(String name);
       }
 
     private GroupTreeViewModel model;
+    
+    private CellTree tree;
 
     public GroupTreeView(GroupTreeViewModel viewModel) {
         this.model = viewModel;
+
+        PithosDisclosurePanel panel = new PithosDisclosurePanel((Resources) GWT.create(Resources.class), "Groups", false);
         /*
          * Create the tree using the model. We use <code>null</code> as the default
          * value of the root node. The default value will be passed to
          * CustomTreeModel#getNodeInfo();
          */
         CellTree.Resources res = GWT.create(BasicResources.class);
-        CellTree tree = new CellTree(model, null, res);
+        tree = new CellTree(model, null, res);
         tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
 
-        initWidget(tree);
+        panel.setContent(tree);
+        
+        initWidget(panel);
     }
 
     public void updateGroupNode(Group group) {
index e47081b..3648646 100644 (file)
 package gr.grnet.pithos.web.client.grouptree;
 
 import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.commands.CreateGroupCommand;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.grouptree.GroupTreeView.Templates;
 
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
-import java.util.Set;
 
 import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
@@ -58,28 +58,6 @@ public class GroupTreeViewModel implements TreeViewModel {
 
     protected Pithos app;
 
-    private ListDataProvider<String> rootDataProvider = new ListDataProvider<String>();
-    
-    private Cell<String> rootCell = new AbstractCell<String>(ContextMenuEvent.getType().getName()) {
-
-               @Override
-               public void render(Context context,     String value, SafeHtmlBuilder sb) {
-            String html = AbstractImagePrototype.create(GroupTreeView.images.groups()).getHTML();
-            sb.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
-            sb.append(Templates.INSTANCE.nameSpan(value));
-               }
-               
-        @Override
-        public void onBrowserEvent(Cell.Context context, com.google.gwt.dom.client.Element parent, String s, com.google.gwt.dom.client.NativeEvent event, com.google.gwt.cell.client.ValueUpdater<String> valueUpdater) {
-            GroupTreeViewModel.this.rootSelectionModel.setSelected(s, true);
-            if (event.getType().equals(ContextMenuEvent.getType().getName())) {
-                GroupContextMenu menu = new GroupContextMenu(app, GroupTreeView.images, null);
-                menu.setPopupPosition(event.getClientX(), event.getClientY());
-                menu.show();
-            }
-        }
-       };
-
        private Cell<Group> groupCell = new AbstractCell<Group>(ContextMenuEvent.getType().getName()) {
 
                @Override
@@ -91,12 +69,14 @@ public class GroupTreeViewModel implements TreeViewModel {
                
         @Override
         public void onBrowserEvent(Cell.Context context, com.google.gwt.dom.client.Element parent, Group group, com.google.gwt.dom.client.NativeEvent event, com.google.gwt.cell.client.ValueUpdater<Group> valueUpdater) {
-            GroupTreeViewModel.this.groupSelectionModel.setSelected(group, true);
-            if (event.getType().equals(ContextMenuEvent.getType().getName())) {
-                GroupContextMenu menu = new GroupContextMenu(app, GroupTreeView.images, group);
-                menu.setPopupPosition(event.getClientX(), event.getClientY());
-                menu.show();
-            }
+               if (!group.equals(createGroup)) {
+                   GroupTreeViewModel.this.groupSelectionModel.setSelected(group, true);
+                   if (event.getType().equals(ContextMenuEvent.getType().getName())) {
+                       GroupContextMenu menu = new GroupContextMenu(app, GroupTreeView.images, group);
+                       menu.setPopupPosition(event.getClientX(), event.getClientY());
+                       menu.show();
+                   }
+               }
         }
        };
 
@@ -124,33 +104,13 @@ public class GroupTreeViewModel implements TreeViewModel {
 
     protected Map<Group, ListDataProvider<User>> userDataProviderMap = new HashMap<Group, ListDataProvider<User>>();
     
-    protected Map<String, Set<File>> sharedFiles = new HashMap<String, Set<File>>();
-
-    SingleSelectionModel<String> rootSelectionModel;
     SingleSelectionModel<Group> groupSelectionModel;
     SingleSelectionModel<User> userSelectionModel;
+    
+    final Group createGroup = new Group("Create new group...");
 
     public GroupTreeViewModel(Pithos _app) {
         app = _app;
-        rootSelectionModel = new SingleSelectionModel<String>();
-       app.addSelectionModel(rootSelectionModel);
-       rootSelectionModel.addSelectionChangeHandler(new SelectionChangeEvent.Handler() {
-                       
-                       @Override
-                       public void onSelectionChange(SelectionChangeEvent event) {
-                               if (rootSelectionModel.getSelectedObject() != null) {
-                                       app.deselectOthers(app.getGroupTreeView(), rootSelectionModel);
-                                       app.showFiles(new HashSet<File>());
-                                       app.showRelevantToolbarButtons();
-                               }
-                               else {
-                                       if (app.getSelectedTree().equals(app.getGroupTreeView()))
-                                               app.setSelectedTree(null);
-                                       if (app.getSelectedTree() == null)
-                                               app.showRelevantToolbarButtons();
-                               }
-                       }
-               });
 
        groupSelectionModel = new SingleSelectionModel<Group>();
        app.addSelectionModel(groupSelectionModel);
@@ -158,10 +118,15 @@ public class GroupTreeViewModel implements TreeViewModel {
                        
                        @Override
                        public void onSelectionChange(SelectionChangeEvent event) {
-                               if (groupSelectionModel.getSelectedObject() != null) {
+                               Group selected = groupSelectionModel.getSelectedObject();
+                               if (selected != null) {
                                        app.deselectOthers(app.getGroupTreeView(), groupSelectionModel);
                                        app.showFiles(new HashSet<File>());
                                        app.showRelevantToolbarButtons();
+                                       if (selected.equals(createGroup)) {
+                                               new CreateGroupCommand(app, null).execute();
+                                               groupSelectionModel.setSelected(createGroup, false);
+                                       }
                                }
                                else {
                                        if (app.getSelectedTree().equals(app.getGroupTreeView()))
@@ -196,48 +161,37 @@ public class GroupTreeViewModel implements TreeViewModel {
     @Override
     public <T> NodeInfo<?> getNodeInfo(T value) {
         if (value == null) {
-               rootDataProvider.getList().add("");
-            return new DefaultNodeInfo<String>(rootDataProvider, rootCell,  rootSelectionModel, null);
-        }
-        else if (value instanceof String) {
                groupsDataProvider.getList().clear();
-               groupsDataProvider.getList().addAll(app.getAccount().getGroups());
+                       groupsDataProvider.getList().addAll(app.getAccount().getGroups());
+                       groupsDataProvider.getList().add(createGroup);
             return new DefaultNodeInfo<Group>(groupsDataProvider, groupCell, groupSelectionModel, null);
         }
-        else { //Group
-               Group g = (Group) value;
-                       if (userDataProviderMap.get(g) == null) {
-                               userDataProviderMap.put(g, new ListDataProvider<User>());
-                       }
-                       final ListDataProvider<User> dataProvider = userDataProviderMap.get(g);
-                       dataProvider.getList().clear();
-                       for (String u : g.getMembers())
-                               dataProvider.getList().add(new User(u, g));
-               return new DefaultNodeInfo<User>(dataProvider, userCell, userSelectionModel, null);
-        }
+       Group g = (Group) value;
+               if (userDataProviderMap.get(g) == null) {
+                       userDataProviderMap.put(g, new ListDataProvider<User>());
+               }
+               final ListDataProvider<User> dataProvider = userDataProviderMap.get(g);
+               dataProvider.getList().clear();
+               for (String u : g.getMembers())
+                       dataProvider.getList().add(new User(u, g));
+       return new DefaultNodeInfo<User>(dataProvider, userCell, userSelectionModel, null);
     }
 
        @Override
     public boolean isLeaf(Object o) {
-        if (o instanceof String) {
-                       return ((String) o).length() == 0 || app.getAccount().getGroups().isEmpty();
+        if (o instanceof User) {
+                       return true;
         }
         else if (o instanceof Group)
                return ((Group) o).getMembers().isEmpty();
-        else if (o != null)
-               return true;
         return false;
     }
        
-       public void initialize() {
-       rootDataProvider.getList().clear();
-       rootDataProvider.getList().add("Groups");
-       }
-
        public void updateGroupNode(Group group) {
                if (group == null) {
                        groupsDataProvider.getList().clear();
                        groupsDataProvider.getList().addAll(app.getAccount().getGroups());
+                       groupsDataProvider.getList().add(createGroup);
                }
                else {
                        if (userDataProviderMap.get(group) == null) {
@@ -251,8 +205,6 @@ public class GroupTreeViewModel implements TreeViewModel {
        }
 
        public Object getSelectedObject() {
-               if (rootSelectionModel.getSelectedObject() != null)
-                       return rootSelectionModel.getSelectedObject();
                if (groupSelectionModel.getSelectedObject() != null)
                        return groupSelectionModel.getSelectedObject();
                if (userSelectionModel.getSelectedObject() != null)
diff --git a/src/gr/grnet/pithos/web/client/grouptree/PithosGroupDisclosurePanel.css b/src/gr/grnet/pithos/web/client/grouptree/PithosGroupDisclosurePanel.css
new file mode 100644 (file)
index 0000000..e838385
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+.disclosurePanel {
+       width: 100%;
+       margin-bottom: 5px;
+}
+
+.header {
+       background-color: #cdde87;
+       height: 28px;
+    width: 100%;
+    padding-left: 6px;
+}
+
+.arrow { 
+       padding-right: 2px;
+}
+
+.content {
+       width: 100%;
+}
index b0c9476..f651f18 100644 (file)
@@ -36,6 +36,7 @@
 package gr.grnet.pithos.web.client.mysharedtree;
 
 import gr.grnet.pithos.web.client.FolderContextMenu;
+import gr.grnet.pithos.web.client.PithosDisclosurePanel;
 import gr.grnet.pithos.web.client.TreeView;
 import gr.grnet.pithos.web.client.foldertree.Folder;
 
@@ -49,13 +50,14 @@ import com.google.gwt.safehtml.shared.SafeHtml;
 import com.google.gwt.user.cellview.client.CellTree;
 import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy;
 import com.google.gwt.user.cellview.client.TreeNode;
+import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.Tree;
 
 public class MysharedTreeView extends Composite implements TreeView {
 
     public void updateChildren(Folder folder) {
-        TreeNode root = ((CellTree) getWidget()).getRootTreeNode();
+        TreeNode root = tree.getRootTreeNode();
         updateChildren(root, folder);
     }
 
@@ -105,18 +107,18 @@ public class MysharedTreeView extends Composite implements TreeView {
         @Source("gr/grnet/pithos/resources/home22.png")
         ImageResource home();
 
-        @Source("gr/grnet/pithos/resources/folder22.png")
+        @Source("gr/grnet/pithos/resources/2folder22.png")
         public ImageResource folderYellow();
 
         @Source("gr/grnet/pithos/resources/mimetypes/document.png")
         ImageResource document();
 
-        @Source("gr/grnet/pithos/resources/othersshared.png")
-        ImageResource othersShared();
-
         @Source("gr/grnet/pithos/resources/myshared22.png")
         ImageResource myShared();
 
+        @Source("gr/grnet/pithos/resources/sharedbyme22.png")
+        ImageResource sharedByMe();
+
         @Source("gr/grnet/pithos/resources/folder_user.png")
         ImageResource sharedFolder();
     }
@@ -130,21 +132,53 @@ public class MysharedTreeView extends Composite implements TreeView {
         public SafeHtml nameSpan(String name);
       }
 
+    interface Style extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Style {
+       @Override
+               String header();
+    }
+
+    interface Resources extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Resources {
+               @Override
+               @Source("PithosMySharedDisclosurePanel.css")
+               Style pithosDisclosurePanelCss();
+
+               @Override
+               @Source("gr/grnet/pithos/resources/sharedbyme22.png")
+       ImageResource icon();
+    }
+
     private MysharedTreeViewModel model;
 
+    private PithosDisclosurePanel panel;
+    
+    private CellTree tree;
+    
+    private CellTree.Resources res = GWT.create(BasicResources.class);
+    
     public MysharedTreeView(MysharedTreeViewModel viewModel) {
         this.model = viewModel;
-        /*
+        
+        panel = new PithosDisclosurePanel((Resources) GWT.create(Resources.class), "Shared by me", false);
+        createTree();
+
+        initWidget(panel);
+    }
+
+       /**
+        * 
+        */
+       void createTree() {
+               /*
          * Create the tree using the model. We use <code>null</code> as the default
          * value of the root node. The default value will be passed to
          * CustomTreeModel#getNodeInfo();
          */
-        CellTree.Resources res = GWT.create(BasicResources.class);
-        CellTree tree = new CellTree(model, null, res);
+               if (tree != null)
+                       tree.removeFromParent();
+        tree = new CellTree(model, null, res);
         tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
-
-        initWidget(tree);
-    }
+        panel.setContent(tree);
+       }
 
 
     @Override
@@ -157,8 +191,12 @@ public class MysharedTreeView extends Composite implements TreeView {
     }
 
        public void updateRoot() {
-               TreeNode root = ((CellTree) getWidget()).getRootTreeNode();
-               root.setChildOpen(0, true);
-               root.setChildOpen(0, false);
+               model.initialize(new Command() {
+                               
+                               @Override
+                               public void execute() {
+                                       createTree();
+                               }
+               });
        }
 }
index 8b98bc2..baf1025 100644 (file)
@@ -42,6 +42,8 @@ import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
 import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
 import gr.grnet.pithos.web.client.mysharedtree.MysharedTreeView.Templates;
+import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeView;
+import gr.grnet.pithos.web.client.othersharedtree.OtherSharedTreeViewModel;
 import gr.grnet.pithos.web.client.rest.GetRequest;
 import gr.grnet.pithos.web.client.rest.RestException;
 
@@ -57,6 +59,7 @@ import com.google.gwt.cell.client.AbstractCell;
 import com.google.gwt.cell.client.Cell;
 import com.google.gwt.cell.client.TextCell;
 import com.google.gwt.cell.client.ValueUpdater;
+import com.google.gwt.cell.client.Cell.Context;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.core.client.Scheduler;
 import com.google.gwt.event.dom.client.ContextMenuEvent;
@@ -77,22 +80,26 @@ public class MysharedTreeViewModel implements TreeViewModel {
 
     protected Pithos app;
 
-    private Cell<Folder> folderCell = new AbstractCell<Folder>() {
+    Folder dummy = new Folder("No files shared by me");
+    
+    private Cell<Folder> folderCell = new AbstractCell<Folder>(ContextMenuEvent.getType().getName()) {
 
        @Override
         public void render(Context context, Folder folder, SafeHtmlBuilder safeHtmlBuilder) {
-            String html = AbstractImagePrototype.create(MysharedTreeView.images.folderYellow()).getHTML();
-            safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+           if (!folder.equals(dummy)) {
+                  String html = AbstractImagePrototype.create(MysharedTreeView.images.folderYellow()).getHTML();
+               safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+           }
             safeHtmlBuilder.append(Templates.INSTANCE.nameSpan(folder.getName()));
         }
 
-        @Override
-        public void onBrowserEvent(Context context, com.google.gwt.dom.client.Element parent, final Folder folder, com.google.gwt.dom.client.NativeEvent event, ValueUpdater<Folder> valueUpdater) {
-            if (event.getType().equals(ContextMenuEvent.getType().getName())) {
-               final int x = event.getClientX();
-               final int y = event.getClientY();
-                MysharedTreeViewModel.this.selectionModel.setSelected(folder, true);
-                app.scheduleFolderHeadCommand(folder, new Command() {
+       @Override
+       public void onBrowserEvent(Context context, com.google.gwt.dom.client.Element parent, final Folder folder, com.google.gwt.dom.client.NativeEvent event, ValueUpdater<Folder> valueUpdater) {
+           if (event.getType().equals(ContextMenuEvent.getType().getName())) {
+               final int x = event.getClientX();
+               final int y = event.getClientY();
+               MysharedTreeViewModel.this.selectionModel.setSelected(folder, true);
+               app.scheduleFolderHeadCommand(folder, new Command() {
                                        
                                        @Override
                                        public void execute() {
@@ -101,14 +108,12 @@ public class MysharedTreeViewModel implements TreeViewModel {
                                menu.show();
                                        }
                                });
-            }
-        }
+           }
+       }
     };
 
     protected ListDataProvider<Folder> firstLevelDataProvider = new ListDataProvider<Folder>();
-
-    private Map<Folder, ListDataProvider<Folder>> dataProviderMap = new HashMap<Folder, ListDataProvider<Folder>>();
-    
     protected SingleSelectionModel<Folder> selectionModel;
 
     public MysharedTreeViewModel(Pithos _app, SingleSelectionModel<Folder> selectionModel) {
@@ -119,37 +124,10 @@ public class MysharedTreeViewModel implements TreeViewModel {
     @Override
     public <T> NodeInfo<?> getNodeInfo(T value) {
         if (value == null) {
-            ListDataProvider<String> rootDataProvider = new ListDataProvider<String>();
-            rootDataProvider.getList().add("Shared by me");
-            return new DefaultNodeInfo<String>(rootDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
-                @Override
-                public SafeHtml render(String object) {
-                    SafeHtmlBuilder builder = new SafeHtmlBuilder();
-                    render(object, builder);
-                    return builder.toSafeHtml();
-                }
-
-                @Override
-                public void render(String object, SafeHtmlBuilder builder) {
-                    String html = AbstractImagePrototype.create(MysharedTreeView.images.myShared()).getHTML();
-                    builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
-                    builder.append(MysharedTreeView.Templates.INSTANCE.nameSpan(object));
-                }
-            }),  null, null);
-        }
-        else if (value instanceof String) {
                fetchSharedContainers(null);
             return new DefaultNodeInfo<Folder>(firstLevelDataProvider, folderCell, selectionModel, null);
         }
-        else {
-            final Folder f = (Folder) value;
-            if (dataProviderMap.get(f) == null) {
-                dataProviderMap.put(f, new ListDataProvider<Folder>());
-            }
-            final ListDataProvider<Folder> dataProvider = dataProviderMap.get(f);
-            fetchFolder(f, dataProvider, false);
-            return new DefaultNodeInfo<Folder>(dataProvider, folderCell, selectionModel, null);
-        }
+        return null;
     }
 
        private void fetchSharedContainers(final Command callback) {
@@ -157,23 +135,17 @@ public class MysharedTreeViewModel implements TreeViewModel {
         GetRequest<AccountResource> getAccount = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), app.getUsername(), path) {
             @Override
             public void onSuccess(final AccountResource _result) {
-               Iterator<Folder> iter = _result.getContainers().listIterator();
-               fetchFolder(iter, new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                                               firstLevelDataProvider.getList().clear();
-                               Folder t = null;
-                               for (Folder c : _result.getContainers()) {
-                                       if (c.isHome())
-                                               firstLevelDataProvider.getList().add(0, c); //Pithos is always first
-                                       else if (!c.isTrash())
-                                               firstLevelDataProvider.getList().add(c);
-                               }
-                                               if (callback != null)
-                                                       callback.execute();
-                                       }
-                               });
+                               firstLevelDataProvider.getList().clear();
+                for (Folder c : _result.getContainers()) {
+                       if (c.isHome())
+                               firstLevelDataProvider.getList().add(0, c); //Pithos is always first
+                       else if (!c.isTrash())
+                               firstLevelDataProvider.getList().add(c);
+                }
+                if (firstLevelDataProvider.getList().isEmpty())
+                       firstLevelDataProvider.getList().add(dummy);
+                               if (callback != null)
+                                       callback.execute();
             }
 
             @Override
@@ -198,14 +170,8 @@ public class MysharedTreeViewModel implements TreeViewModel {
        @Override
     public boolean isLeaf(Object o) {
                if (o == null)
-                       return false;
-               else if (o instanceof Folder) {
-            Folder f = (Folder) o;
-            return f.getSubfolders().isEmpty();
-        }
-               else {
                        return firstLevelDataProvider.getList().isEmpty();
-               }
+               return true;
     }
        
        private native void log(String msg) /*-{
@@ -250,29 +216,16 @@ public class MysharedTreeViewModel implements TreeViewModel {
     }
 
     public void updateFolder(Folder folder, boolean showfiles) {
-        if (dataProviderMap.get(folder) == null) {
-            dataProviderMap.put(folder, new ListDataProvider<Folder>());
-        }
-        final ListDataProvider<Folder> dataProvider = dataProviderMap.get(folder);
-        fetchFolder(folder, dataProvider, showfiles);
+        fetchFolder(folder,showfiles);
     }
 
-    public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles) {
-        String path = "/" + f.getContainer() + "?format=json&shared=&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
+    public void fetchFolder(final Folder f, final boolean showfiles) {
+        String path = "/" + f.getContainer() + "?format=json&shared=" + URL.encodeQueryString(f.getPrefix());
         GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
             @Override
             public void onSuccess(final Folder _result) {
                 if (showfiles)
                     app.showFiles(_result);
-                Iterator<Folder> iter = new ArrayList<Folder>(_result.getSubfolders()).listIterator();
-                fetchFolder(iter, new Command() {
-                    @Override
-                    public void execute() {
-                        dataProvider.getList().clear();
-                               dataProvider.getList().addAll(_result.getSubfolders());
-                        app.getMySharedTreeView().updateChildren(f);
-                    }
-                });
             }
 
             @Override
diff --git a/src/gr/grnet/pithos/web/client/mysharedtree/PithosMySharedDisclosurePanel.css b/src/gr/grnet/pithos/web/client/mysharedtree/PithosMySharedDisclosurePanel.css
new file mode 100644 (file)
index 0000000..f91e754
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+.disclosurePanel {
+       width: 100%;
+       margin-top: 20px;
+       margin-bottom: 5px;
+}
+
+.header {
+       background-color: #e9ddaf;
+       height: 28px;
+    width: 100%;
+    padding-left: 6px;
+}
+
+.arrow { 
+       padding-right: 2px;
+}
+
+.content {
+       width: 100%;
+}
index 739ce18..b003bec 100644 (file)
 package gr.grnet.pithos.web.client.othersharedtree;
 
 import gr.grnet.pithos.web.client.FolderContextMenu;
+import gr.grnet.pithos.web.client.PithosDisclosurePanel;
 import gr.grnet.pithos.web.client.TreeView;
 import gr.grnet.pithos.web.client.foldertree.Folder;
 
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.resources.client.ClientBundle.Source;
 import com.google.gwt.resources.client.ImageResource.ImageOptions;
 import com.google.gwt.resources.client.ImageResource.RepeatStyle;
 import com.google.gwt.safehtml.client.SafeHtmlTemplates;
@@ -55,7 +55,7 @@ import com.google.gwt.user.client.ui.Tree;
 public class OtherSharedTreeView extends Composite implements TreeView {
 
     public void updateChildren(Folder folder) {
-        TreeNode root = ((CellTree) getWidget()).getRootTreeNode();
+        TreeNode root = tree.getRootTreeNode();
         updateChildren(root, folder);
     }
 
@@ -105,13 +105,13 @@ public class OtherSharedTreeView extends Composite implements TreeView {
         @Source("gr/grnet/pithos/resources/home22.png")
         ImageResource home();
 
-        @Source("gr/grnet/pithos/resources/folder22.png")
+        @Source("gr/grnet/pithos/resources/2folder22.png")
         public ImageResource folderYellow();
 
         @Source("gr/grnet/pithos/resources/mimetypes/document.png")
         ImageResource document();
 
-        @Source("gr/grnet/pithos/resources/othersshared.png")
+        @Source("gr/grnet/pithos/resources/sharedtome22.png")
         ImageResource othersShared();
 
         @Source("gr/grnet/pithos/resources/myshared22.png")
@@ -133,20 +133,40 @@ public class OtherSharedTreeView extends Composite implements TreeView {
         public SafeHtml nameSpan(String name);
       }
 
+    interface Style extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Style {
+       @Override
+               String disclosurePanel();
+    }
+
+    interface Resources extends gr.grnet.pithos.web.client.PithosDisclosurePanel.Resources {
+               @Override
+               @Source("PithosOtherSharedDisclosurePanel.css")
+               Style pithosDisclosurePanelCss();
+
+               @Override
+               @Source("gr/grnet/pithos/resources/sharedtome22.png")
+       ImageResource icon();
+    }
+
     private OtherSharedTreeViewModel model;
 
+    private CellTree tree;
+    
     public OtherSharedTreeView(OtherSharedTreeViewModel viewModel) {
         this.model = viewModel;
+        
+        PithosDisclosurePanel panel = new PithosDisclosurePanel((Resources) GWT.create(Resources.class), "Shared to me", false); 
         /*
          * Create the tree using the model. We use <code>null</code> as the default
          * value of the root node. The default value will be passed to
          * CustomTreeModel#getNodeInfo();
          */
         CellTree.Resources res = GWT.create(BasicResources.class);
-        CellTree tree = new CellTree(model, null, res);
+        tree = new CellTree(model, null, res);
         tree.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED);
 
-        initWidget(tree);
+        panel.setContent(tree);
+        initWidget(panel);
     }
 
 
index 63c2426..588f1cc 100644 (file)
@@ -74,15 +74,16 @@ import com.google.gwt.view.client.TreeViewModel;
 
 public class OtherSharedTreeViewModel implements TreeViewModel {
 
-       private static final String treeTitle = "Shared to me";
     protected Pithos app;
 
+    String dummy = "No shares by others yet";
+
     private Cell<Folder> folderCell = new AbstractCell<Folder>(ContextMenuEvent.getType().getName()) {
 
        @Override
         public void render(Context context, Folder folder, SafeHtmlBuilder safeHtmlBuilder) {
             String html = AbstractImagePrototype.create(OtherSharedTreeView.images.folderYellow()).getHTML();
-            safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+               safeHtmlBuilder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
             safeHtmlBuilder.append(Templates.INSTANCE.nameSpan(folder.getName()));
         }
 
@@ -121,43 +122,27 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
     @Override
     public <T> NodeInfo<?> getNodeInfo(T value) {
         if (value == null) {
-            rootDataProvider.getList().add(treeTitle);
-            return new DefaultNodeInfo<String>(rootDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
-                @Override
-                public SafeHtml render(String object) {
+               fetchSharingUsers(null);
+            return new DefaultNodeInfo<String>(userLevelDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
+
+                               @Override
+                               public SafeHtml render(String object) {
                     SafeHtmlBuilder builder = new SafeHtmlBuilder();
                     render(object, builder);
                     return builder.toSafeHtml();
-                }
+                               }
 
-                @Override
-                public void render(String object, SafeHtmlBuilder builder) {
-                    String html = AbstractImagePrototype.create(OtherSharedTreeView.images.othersShared()).getHTML();
-                    builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+                               @Override
+                               public void render(String object, SafeHtmlBuilder builder) {
+                    if (!object.equals(dummy)) {
+                       String html = AbstractImagePrototype.create(OtherSharedTreeView.images.myShared()).getHTML();
+                       builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
+                    }
                     builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
-                }
-            }),  null, null);
+                               }
+                       }), null, null);
         }
         else if (value instanceof String) {
-               if (value.equals(treeTitle)) {
-                       fetchSharingUsers(null);
-                   return new DefaultNodeInfo<String>(userLevelDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
-
-                                       @Override
-                                       public SafeHtml render(String object) {
-                           SafeHtmlBuilder builder = new SafeHtmlBuilder();
-                           render(object, builder);
-                           return builder.toSafeHtml();
-                                       }
-
-                                       @Override
-                                       public void render(String object, SafeHtmlBuilder builder) {
-                           String html = AbstractImagePrototype.create(OtherSharedTreeView.images.user()).getHTML();
-                           builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
-                           builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
-                                       }
-                               }), null, null);
-               }
                        String username = (String) value;
                        if (userDataProviderMap.get(username) == null) {
                                userDataProviderMap.put(username, new ListDataProvider<Folder>());
@@ -183,6 +168,8 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
             public void onSuccess(final SharingUsers _result) {
                 userLevelDataProvider.getList().clear();
                 userLevelDataProvider.getList().addAll(_result.getUsers());
+                if (userLevelDataProvider.getList().isEmpty())
+                       userLevelDataProvider.getList().add(dummy);
                 Iterator<String> iter = _result.getUsers().iterator();
                 fetchSharedContainers(iter, callback);
             }
@@ -230,14 +217,12 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
        @Override
     public boolean isLeaf(Object o) {
                if (o == null)
-                       return false;
+                       return userLevelDataProvider.getList().isEmpty();
                else if (o instanceof Folder) {
             Folder f = (Folder) o;
             return f.getSubfolders().isEmpty();
         }
                else {
-                       if (o.equals(treeTitle))
-                               return userLevelDataProvider.getList().isEmpty();
                        ListDataProvider<Folder> dp = userDataProviderMap.get(o);
                        if (dp != null)
                                return dp.getList().isEmpty();
diff --git a/src/gr/grnet/pithos/web/client/othersharedtree/PithosOtherSharedDisclosurePanel.css b/src/gr/grnet/pithos/web/client/othersharedtree/PithosOtherSharedDisclosurePanel.css
new file mode 100644 (file)
index 0000000..8a910f3
--- /dev/null
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2012 GRNET S.A. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials
+ *      provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The views and conclusions contained in the software and
+ * documentation are those of the authors and should not be
+ * interpreted as representing official policies, either expressed
+ * or implied, of GRNET S.A.
+ */
+.disclosurePanel {
+       width: 100%;
+       margin-bottom: 20px;
+}
+
+.header {
+       background-color: #74aec9;
+       height: 28px;
+    width: 100%;
+    padding-left: 6px;
+}
+
+.arrow { 
+       padding-right: 2px;
+}
+
+.content {
+       width: 100%;
+}
diff --git a/src/gr/grnet/pithos/web/public/images/separator.png b/src/gr/grnet/pithos/web/public/images/separator.png
new file mode 100644 (file)
index 0000000..e0c13c3
Binary files /dev/null and b/src/gr/grnet/pithos/web/public/images/separator.png differ
index 45d17ed..35f52d0 100644 (file)
  */
 body {
        color: black;
-       font: 13px Verdana, 'PT Sans', sans-serif;
+       font-family: Verdana, 'PT Sans', sans-serif;
+       font-size: 13px;
        margin: 8px;
        margin-top: 3px;
        background-color: transparent;
 }
 
 table td {
-       font: 13px Verdana, 'PT Sans', sans-serif;
+       font-family: Verdana, 'PT Sans', sans-serif;
+       font-size: 13px;
 }
 
 .pithos-outer {
@@ -122,13 +124,13 @@ a.info:hover div {
 }
 
 .pithos-DialogBox .close {
-       background: url(images/close-popup.png) no-repeat;
        cursor: pointer;
        position: absolute;
        width: 13px;
        height: 13px;
        top: 12px;
-       right: 7px;
+       right: 27px;
+       font-size: 0.8em;
 }
 
 .pithos-DialogBox .dialogMiddleCenter {
@@ -178,12 +180,16 @@ table.pithos-permList.props-labels {
 .props-labels {
        font-size: 80%;
        font-weight: bold;
+       padding-left: 10px;
+       padding-right: 10px;
 }
 
 .props-toplabels {
        font-size: 80%;
        font-weight: bold;
        font-style: italic;
+       padding-left: 10px;
+       padding-right: 10px;
 }
 
 .props-values {
@@ -339,15 +345,20 @@ table.pithos-permList.props-labels {
        padding-left: 4;
 }
 
-.pithos-treeHeader {
-       background-color: #74aec9;
-       height: 25px;
-    width: 100%;
+.pithos-statistics {
+       color: black;
+       padding-top: 10px;
+       padding-bottom: 10px;
 }
 
-.pithos-statistics {
-       color: white;
-       padding: 5px;
+.pithos-statistics .gwt-HTML {
+       font-size: smaller;
+}
+
+.pithos-statisticsSeparator {
+       background: url(images/separator.png) no-repeat;
+       width: 100%;
+       height: 3px;
 }
 
 .pithos-splitPanel {
@@ -377,8 +388,9 @@ table.pithos-permList.props-labels {
     text-align: center;
     height: auto;
     padding: 8px;
-    width: 146px;
-    border: none;
+    width: 134px;
+    border: 0px;
+    color: black;
 }
 
 .pithos-uploadButton-loading {
@@ -733,8 +745,3 @@ a.pithos-tag {
 .pithos-versionList {
        padding-right: 5px;
 }
-
-
-.glg5-e2bki {
-    background: url(images/share.png) no-repeat 5px 9px !important;
-}
index 8caca2d..371c0f8 100644 (file)
@@ -13,7 +13,7 @@
        padding: 5px 6px;\r
        margin-right: 4px;\r
 /*    background: #f3f3f3 url('../img/buttons.png') no-repeat 0 center;*/\r
-       background-color: #4085A5;\r
+       background-color: #0A0;\r
        outline: 0;\r
 \r
     /* Optional rounded corners for browsers that support it */\r
 \r
 .plupload_add {\r
 /*     background-position: -181px center;*/\r
+       background-color: #0A0;\r
 }\r
 \r
 .plupload_wrapper {\r
-       font: normal 11px Verdana,sans-serif;\r
+       font-family: Verdana, 'PT Sans', sans-serif;\r
+       font-size: 100%;\r
        width: 100%;\r
 }\r
 \r
 /*     color: #FFF;*/\r
 }\r
 .plupload_header_title {\r
-       font: normal 18px sans-serif;\r
-       padding: 6px 0 3px;\r
+       font-size: 1.2em;\r
+       color: white;\r
+       padding: 6px 14px 3px;\r
 }\r
 .plupload_header_text {\r
-       font: normal 12px sans-serif;\r
+       font-size: 0.8em;\r
+       color: #4085A5;\r
+       padding-left: 14px;\r
 }\r
 \r
 .plupload_filelist {\r
 \r
 .plupload_scroll .plupload_filelist {\r
        height: 185px;\r
-       background: #F5F5F5;\r
        overflow-y: scroll;\r
 }\r
 \r
 .plupload_filelist li {\r
        padding: 10px 8px;\r
-       background: #F5F5F5 url('../img/backgrounds.gif') repeat-x 0 -156px;\r
-       border-bottom: 1px solid #DDD;\r
+       background: #EEE\r
 }\r
 \r
 .plupload_filelist_header, .plupload_filelist_footer {\r
-/*     background: #DFDFDF;*/\r
-       background: #74aec9;\r
        padding: 8px 8px;\r
-/*     color: #42454A;*/\r
-}\r
-.plupload_filelist_header {    \r
-       border-top: 1px solid #EEE;\r
-       border-bottom: 1px solid #CDCDCD;\r
+       color: #4085A5;\r
+       border-top: 1px solid #AAA;\r
 }\r
 \r
 .plupload_filelist_footer {/*border-top: 1px solid #FFF; height: 22px; line-height: 20px;*/ vertical-align: middle;}\r
 .plupload_file_name {float: left; overflow: hidden}\r
-.plupload_file_status {/*color: #777;*/}\r
-.plupload_file_status span {/*color: #42454A;*/}\r
+.plupload_file_status {}\r
+.plupload_file_size span {color: #FF7F2A;}\r
 .plupload_file_size, .plupload_file_status, .plupload_progress {\r
        float: right;\r
        width: 80px;\r
 }\r
+\r
+.plupload_total_status {\r
+       color: #FF7F2A;\r
+}\r
+\r
 .plupload_file_size, .plupload_file_status, .plupload_file_action {text-align: right;}\r
 \r
 .plupload_filelist .plupload_file_name {width: 205px}\r
 }\r
 \r
 li.plupload_uploading {\r
-       background: #ECF3DC url('../img/backgrounds.gif') repeat-x 0 -238px;\r
+       background: #EEE;\r
 }\r
 li.plupload_done {color:#AAA}\r
 \r
@@ -146,6 +149,7 @@ li.plupload_done a {
 \r
 .plupload_progress, .plupload_upload_status {\r
        display: none;\r
+       color: #FF7F2A;\r
 }\r
 \r
 .plupload_progress_container {\r
@@ -157,7 +161,7 @@ li.plupload_done a {
 .plupload_progress_bar {\r
        width: 0px;\r
        height: 7px;\r
-       background: #CDEB8B;\r
+       background: #FF7F2A;\r
 }\r
 \r
 .plupload_scroll .plupload_filelist_header .plupload_file_action, .plupload_scroll .plupload_filelist_footer .plupload_file_action {\r