Merge branch 'packaging' into debian
authorKostas Papadimitriou <kpap@grnet.gr>
Thu, 19 Apr 2012 10:01:33 +0000 (13:01 +0300)
committerKostas Papadimitriou <kpap@grnet.gr>
Thu, 19 Apr 2012 10:01:33 +0000 (13:01 +0300)
33 files changed:
.gitignore
docs/source/webclient.rst
snf-pithos-webclient/Changelog
snf-pithos-webclient/README
snf-pithos-webclient/conf/20-snf-pithos-webclient-cloudbar.conf
snf-pithos-webclient/pithos_webclient/settings.py
snf-pithos-webclient/pithos_webclient/views.py
snf-pithos-webclient/setup.py
src/gr/grnet/pithos/web/client/DeleteFileDialog.java
src/gr/grnet/pithos/web/client/FileContextMenu.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 [new file with mode: 0644]
src/gr/grnet/pithos/web/client/FileUploadDialog.java
src/gr/grnet/pithos/web/client/FileVersionsDialog.java
src/gr/grnet/pithos/web/client/FolderPermissionsDialog.java
src/gr/grnet/pithos/web/client/FolderPropertiesDialog.java
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/Toolbar.java
src/gr/grnet/pithos/web/client/ToolsMenu.java
src/gr/grnet/pithos/web/client/commands/PasteCommand.java
src/gr/grnet/pithos/web/client/commands/PropertiesCommand.java
src/gr/grnet/pithos/web/client/commands/RefreshCommand.java
src/gr/grnet/pithos/web/client/commands/RestoreTrashCommand.java
src/gr/grnet/pithos/web/client/commands/ToTrashCommand.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/mysharedtree/MysharedTreeView.java
src/gr/grnet/pithos/web/client/mysharedtree/MysharedTreeViewModel.java
src/gr/grnet/pithos/web/client/othersharedtree/OtherSharedTreeViewModel.java

index 93891d1..f1bc3ca 100644 (file)
@@ -17,8 +17,8 @@ gwt-unitCache
 */dist/
 */build/
 */pithos_webclient/version.py
-*/pithos_webclient/templates/pithos_web_client/*
-*/pithos_webclient/static/pithos_web_client/*
+*/pithos_webclient/templates/pithos_webclient/*
+*/pithos_webclient/static/pithos_webclient/*
 distribute*.tar.gz
 distribute*.egg
 docs/build
index de9a186..b4e89ed 100644 (file)
@@ -3,60 +3,107 @@ Pithos+ Web Client
 
 Introduction
 ------------
-
-Document Revisions
-^^^^^^^^^^^^^^^^^^
-
-=====================  =====================================
-Revision               Description
-=====================  =====================================
-0.1 (Mar 17, 2012)     Initial release.
-=====================  =====================================
+The Pithos+ Web client documentation contains information about installation and configuration of the web client along with information about the development of the client (development environment, tools, libraries, API usage etc).
 
 Build instructions
 ------------------
-prerequisites: git, jdk 1.6, ant
+Prerequisites: git, jdk 1.6, ant
 
 First get the source from the git repository
 
 git clone https://code.grnet.gr/git/pithos-web-client
 
+Enter the newly created folder
+
 cd pithos-web-client
 
-Edit the file runtime.properties and set the loginUrl and cloudbar properties to the correct values eg.
+and run ant
 
-loginUrl=https://accounts.staging.okeanos.grnet.gr/im/login?next=https%3A//pithos.staging.okeanos.grnet.gr/ui
+ant
 
-CLOUDBAR_ACTIVE_SERVICE = cloud;
+Now go to the output folder
 
-CLOUDBAR_LOCATION = https://accounts.staging.okeanos.grnet.gr/static/im/cloudbar/
+cd bin/www/gr.grnet.pithos.web.Pithos
 
-CLOUDBAR_SERVICES = https://accounts.staging.okeanos.grnet.gr/im/get_services
+This folder contains the "binaries" (html and javascript actually). Those files should be put somewhere to be served by the web server.
+For deploying to pithos.dev.grnet.gr, upload everything to /var/www/pithos_web_client where they are served under /ui.
 
-CLOUDBAR_MENU = https://accounts.staging.okeanos.grnet.gr/im/get_menu
+Important reminder: Due to Same-Origin-Policy the web client should be served under the same domain as the API.
 
-Then run ant
+Configuration
+-------------
 
-ant
+All configuration exists as javascript variables in index.html file. The things that need to be configured are:
 
-cd bin/www/gr.grnet.pithos.web.Pithos
+loginUrl: The url that the client will redirect the user if she is not logged in (defailt: /im/login?next=). The next= parameter is determined automatically.
 
-This folder contains the "binaries" (html and javascript actually). Those files should be put somewhere to be served by the web server.
-For deploying to pithos.dev.grnet.gr, upload everything to /var/www/pithos_web_client where they are served under /ui.
+authCookie: The name of the authentication cookie that is set by the login process which is external to the web client (default: _pithos2_a).
 
-Important reminder: Due to Same-Origin-Policy the web client should be served under the same domain as the API.
+feedbackUrl: The url that the client should use to POST feedback messages from the user when an error occurs (default: /im/feedback).
+
+The CLOUDBAR_* set of variables is related to the bar that is displayed on the top of the web client 's page. This bar is used to navigate to other services of the cloud and also contains a menu for sendind feedback, inviting other people, logout etc. This bar is also externally configured and the web client just loads it as a script.
+
+CLOUDBAR_ACTIVE_SERVICE: The service that we currently see (in case of the web client it is always pithos).
+
+CLOUDBAR_LOCATION: The url that tha cloudbar script is loaded from (default: /static/im/cloudbar/).
+
+CLOUDBAR_SERVICES: The url that is used to get the available service (default: /im/get_services).
+
+CLOUDBAR_MENU: The url that the menu is loaded from (default: /im/get_menu).
+
+Development environment
+-----------------------
+The development environment used is Eclipse Indigo with the Google Plugin for Eclipse but other environments can be used without problems. The libraries needed for development is
+
+Google Web Toolkit (GWT) v.2.4.0 (http://developers.google.com/web-toolkit/)
+
+The gwt-user.jar is needed in the classpath in order to compile the source. The gwt-dev.jar is needed to run the development mode server for debugging.
+
+All dependencies are downloaded automatically by the ant build script (build.xml) in the dependencies folder if not already found there.
+
+Building
+^^^^^^^^
+Building the project consists just of compiling the java source into javascript and html by the GWT compiler. This is done by the ant script (ant target "gwt-compile")
+
+Debugging
+^^^^^^^^^
+Debugging is done using the GWT development server. The ant script has a special target (run-web-dev-mode) which starts the devmode server, but one can do the same thing from inside Eclipse. In order to use the devmode server, the GWT plugin is needed in the browser. This way the browser communicates with the devmode server and the developer can set breakpoints, examine variable values, evaluate expressions etc for the application that runs in the browser.
 
 Technology and tools
 --------------------
-Pithos+ web client is a gwt application. It is written in Java and compiled to javascript that runs in the browser.
+Pithos+ web client is a gwt application. It is written in Java and compiled to javascript that runs in the browser. More info about gwt can be found here http://developers.google.com/web-toolkit/
 
 General architecture
 --------------------
 
+The web client does an adaptation of the container/object server-side data model to the more user-friendly folder/file data model. The client uses the API to retrieve info about the containers and objects from the server and displays them in a tree-like structure. It uses two special gwt widgets, CellTree (https://developers.google.com/web-toolkit/doc/latest/DevGuideUiCellWidgets#celltree) and CellTable (https://developers.google.com/web-toolkit/doc/latest/DevGuideUiCellTable) for the folder tree and filelist accordingly. The CellTree widget initiates calls to the API at the beginning and each time a subtree is expanded in order to fetch all info needed to display the subfolders. That way the datamodel is controlled by the widget.
+
+Source code structure
+---------------------
+Java source code consists of the following packages:
+
+gr.grnet.pithos.web.client: This is the root packages that containes the Pithos class which is the application entry point and various utility classes like menus, dialogs etc.
+
+gr.grnet.pithos.web.client.foldertree: All classes related to the datamodel and tree widget that displays containers, folders and files.
+
+gr.grnet.pithos.web.client.mysharedtree: All classes related to the datamodel and tree widget that displays the objects shared by me.
+
+gr.grnet.pithos.web.client.othershared: All classes related to the datamodel and tree widget that displays the objects shared to me by other users
+
+gr.grnet.pithos.web.client.grouptree: All classes related to the datamodel and tree widget that displays the groups and users used by the user in order to share files to groups of people more easily.
+
+gr.grnet.pithos.web.client.commands: This packages contains the commands issued by the various menus (right-click menus and toolbar).
+
+gr.grnet.pithos.web.client.rest: This package contains the classes that define the HTTP requests made to the API
+
+gr.grnet.pithos.resources: This folder contains various images used as icons in the application 's UI. Those images are embeded in the javascript code by the GWT compiler for efficiency and therefore they are not served as static files.
+
+gr.grnet.pithos.web.public: This folder contains the index.html page of the application and all related css and other files loaded by it (like the plupload scripts for multiple file uploading).
+
 Authentication
 --------------
 
-Authentication is provided by an external service. Upon loading the web client checks for the existence of the authentication cookie named '_pithos2_a'. If the cookie is present then it is parsed for the username and authentication token. The format of the cookie content is
+Authentication is provided by an external service. Upon loading,, the web client checks for the existence of the authentication cookie named '_pithos2_a'. If the cookie is present then it is parsed for the username and authentication token. The format of the cookie content is
 
 username|token
 
@@ -64,14 +111,14 @@ These username and token are used for every request to the server. If at any tim
 
 If the auth cookie is not present in the first place then the user is immediately redirected to the login page.
 
-The login page url is defined in the runtime.properties file and it must end with a 'next=' url parameter. The value of the parameter will be determined automatically. If the parameter is not present then the login page will not be able to redirect back to the client after a successful login and the use will end up at her profile page.
+The login page url is defined in the index.html file and it must end with a 'next=' url parameter. The value of the parameter will be determined automatically. If the parameter is not present then the login page will not be able to redirect back to the client after a successful login and the user will end up at her profile page.
 
 API Usage
 ---------
 
 Initialization
 ^^^^^^^^^^^^^^
-Upon loading, the web client performs the followinf steps:
+Upon loading, the web client performs the following steps:
 
 Ckeck if the user is authenticated (auth cookie present)
 
@@ -81,7 +128,7 @@ Requests the server for the user account and files. This is done in various stag
 
 GET /v1/username?format=json
 
-If there is a container named 'pithos' and a container named 'trash' then it proceeds to the folder tree construction. Otherwise the missing containers will be created with a request
+If there is a container named 'pithos' and a container named 'trash' then it proceeds to the folder tree construction. Otherwise the missing containers will be created with requests
 
 PUT /v1/username/pithos
 
@@ -89,22 +136,131 @@ PUT /v1/username/trash
 
 Constructing the folder tree
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+The folder tree displays in a tree structure all the user 's containers (including trash). For each container a request is made
 
+GET /v1/username/pithos?format=json&delimiter=/&prefix=
 
-Constructing the My Shared tree
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+to get the first level of folders (either actual objects with application/folder content type or virtual prefixes). The home folder (pithos) is always displayed first, selected and expanded and the trash container is always last.
 
-Constructing the Others' Shared tree
+Due to the pithos container being programmatically selected and expanded at the beginning, additional requests 
+
+GET /v1/username/pithos?format=json&delimiter=/&prefix=pithos_subfolder1
+
+are made to the server to fetch details of the subfolders. We need to know if a subfolder has its own subfolders so that we display the cross sign next to it.
+
+Constructing the "Shared by me" tree
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+My shared tree construction is a bit more complicated. All files that are shared individualy (not through sharing their parent folder) are displayed directly in the root of the tree (inside the 'Shared by me' folder).
+
+All shared folders are displayed in tree structure under the root.
+
+The above means that the client has to make a series of requests to collect all shared items and display them accordingly.
+
+First a
+
+GET /v1/username/container?format=json&delimiter=/&prefix=
+
+is made for each container. If the container is shared it is added to the tree (under "Shared by me") and the client continues to the next container (this has to be re-visited because it was based on the fact that due to the permission inheritance the subfolders are also shared. Since the inheritance has been removed this is no longer valid).
+
+If the container is not shared we have to go deeper to find possible shared subfolders and files. So we examine each file in the folder and if shared we add it in the "Shared by me" folder and we also do a nested iteration getting each subfolder
+
+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
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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.
+
+GET /v1?format=json
+
+For each of the users we do an additional
+
+GET /v1/username?format=json
+
+to get the containers shared by the user and for each container we do the same sequence of requests as in the "Shared by me" case. The difference here is that we don't need to check if the container/folder/file is shared because all requests with a different username always return only objects that are visible to the logged-on user.
 
 Constructing the Groups tree
 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-File sharing
-^^^^^^^^^^^^
+The groups tree is contructed with the initial request for the user account data which returns the groups defined by the user along with their members.
+
+Functionality
+-------------
+The web client provides functionality which is typical to a file manager like copy/cut/paste of individual files, create/rename/delete of folders, upload/rename/delete files etc. All such operations are done by using single calls to the API or combination of calls.
+
+Folder operations
+^^^^^^^^^^^^^^^^^
+Folder creation
+"""""""""""""""
+is done by the FolderPropertiesDialog class with a request
+
+PUT /v1/username/container/path/to/new/folder
+
+Folder removal
+""""""""""""""
+is done by the DeleteFolderDialog class and is a bit more complicated because the files and subfolders must be deleted first. A request
+
+GET /v1/username/container?format=json&delimiter=/&prefix=/path/to/folder
+
+is made to retrieve all objects with names starting with the folder 's prefix. All objects are deleted with requests
+
+DELETE /v1/username/container/path/to/folder/file
 
+and if any of those objects is a marker object (folder) itself the same procedure is followed recursively. Finally a 
+
+DELETE /v1/username/container/path/to/folder
+
+is made to delete the initial folder.
+
+Folder rename
+"""""""""""""
+is done by a 
+
+PUT /v1/username/container/path/to/new/foldername
+
+to create a folder with the new name, followed by recursive copy operations (see below about copy/move/paste) to move all folder 's children under the new one. Finally, a folder deletion is done as described earlier.
+
+File Cut/Copy/Paste
+"""""""""""""""""""
+Cut/Copy operations on folders just put the objects in an internal clipboard. The Paste command does the actual job of copying/moving.
+
+Folder copy is done by creating a folder at the new location with a PUT and then recursively copy all subfolders and files.
+Folder move is done the same way followed by a deletion of the initial folder. It is obvious that a copy/move of a big subtree will result in a great number of API requests.
+
+File Operations
+^^^^^^^^^^^^^^^
 File uploading
-^^^^^^^^^^^^^^
+""""""""""""""
+File uploading is done using the plupload http://www.plupload.com/ plugin.
+
+File rename
+"""""""""""
+is done by FilePropertiesDialog class with a
+
+PUT /v1/username/container/path/to/newfilename
+
+with X-Move-From header containing the old path.
+
+File delete
+"""""""""""
+is done by DeleteFileDialog class with a simple
+
+DELETE /v1/username/container/path/to/file
+
+File Cut/Copy/Paste
+"""""""""""""""""""
+Cut/Copy operations on files just put the objects in an internal clipboard. The Paste command does the actual job of copying/moving.
+
+In case of copy, a sequence (if multiple files are copied) of PUT commands is issued to the new path, with X-Copy-From header
+In case of cut, the same PUT commands have X-Move-From header set.
+
+File/Folder sharing
+^^^^^^^^^^^^^^^^^^^
+Sharing of file and folders with other users is done by setting permissions for other users or groups of users. The FolderPermissionsDialog/FilePermissionsDialog classes display the corresponding UI and perform the API calls. Permissions are set with
+
+POST /v1/username/container/path/to/object
+
+with the X-Object-Sharing containing the permissions (see Pithos+ development guide).
 
-File Copy/Cut/Paste operations
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
\ No newline at end of file
+In the case of a virtual folder (no marker object) the above operation will return 404 (Not Found) and a PUT request is needed to create the marker and then repeat the POST.
\ No newline at end of file
index e8549cc..2e1040e 100644 (file)
@@ -1,6 +1,11 @@
 Changelog
 =========
 
+v0.8.7
+------
+
+- Use PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE setting to set the cloudbar active
+  service.
 
 v0.8.5
 ------
index cf16a97..490e832 100644 (file)
@@ -1,14 +1,80 @@
 snf-pithos-webclient
-=====================
-
-This is the python package of the synnefo pithos ui frontend
-webapp. It consist of a django application module which includes
-a prebuilt version of the pithos ui gwt project contained in
-`../src` directory.
-
-The gwt built files are not included in the repository. Ant
-hooks has been added in setup.py so that each time you run ``python
-setup.py {develop, install, sdist}`` ant build is executed and
-compiled js and other asset files are placed in the appropriate
-locations within the python module to be packaged/installed.
+********************
+
+This is the python package of the pithos frontend web application. It consists
+of a django application module which includes a prebuilt version of the pithos
+gwt project contained in `../src` directory.
+
+The gwt build files are not included in the repository. Ant hooks has been
+added in setup.py so that each time you run ``python setup.py {develop,
+install, sdist}`` ant build gets executed automatically for you.  Additionally
+after each successfull build, compiled js and other asset files are copied in
+the appropriate locations so that they will get included in the created python
+package.
+
+
+Installation
+============
+
+1. Install the ``snf-pithos-webclient`` python package:
+
+    pip install snf-pithos-webclient -f http://docs.dev.grnet.gr/pypi/
+
+2. Add ``pithos_webclient`` in your django project INSTALLED_APPS setting.
+
+3. Configure your web server to serve package static files placed in
+   pithos_web_client/static/pithos_web_client under the
+   ``/static/pithos_web_client`` url (``/static/`` is the default django
+   MEDIA_URL).
+
+
+Available settings
+==================
+
+The pithos webclient use the following settings 
+
+
+PITHOS_UI_LOGIN_URL
+-------------------
+Web client checks for existing ``PITHOS_UI_AUTH_COOKIE_NAME`` cookie on the
+browser and if found, uses the stored token to make requests to the pithos api
+service. If cookie is not found or if api response with 401 error, the
+application will redirect to the ``PITHOS_UI_LOGIN_URL``. ``next`` parameter
+gets automatically appended in the url by the webclient.
+
+**default value:** ``https://accounts.okeanos.grnet.gr/im/login?next=``
+
+
+PITHOS_UI_FEEDBACK_URL
+----------------------
+Should be set to match your astakos deployment feedback endpoint. This is used
+in error messages, if user want to submit the error as feedback to the service
+administrators.
+
+**default value:** ``https://accounts.okeanos.grnet.gr/im/feedback``
+
+
+PITHOS_UI_AUTH_COOKIE_NAME
+--------------------------
+The cookie name the webclient will check for user authenticity. This
+should match the ``ASTAKOS_COOKIE_NAME`` setting of your astakos deployment.
+
+**default value:** ``_pithos2_a``
+
+
+PITHOS_CLOUDBAR_ACTIVE_SERVICE
+------------------------------
+This is passed as a setting to the cloudbar js script to set focus to the
+appropriate service menu. This should match the `id` key of
+``ASTAKOS_CLOUD_SERVICES`` entry which refers to pithos application.
+
+**default value:** ``pithos``
+
+
+CLOUDBAR_SETTINGS
+-----------------
+Webclient also makes use of the ``cloudbar`` context processor located in
+``snf-common`` package which requires ``CLOUDBAR_ACTIVE``,
+``CLOUDBAR_LOCATION``, ``CLOUDBAR_COOKIE_NAME``, ``CLOUDBAR_SERVICES_URL``,
+``CLOUDBAR_MENU_URL`` settings to be set.
 
index 5f2005e..4d89a41 100644 (file)
@@ -2,7 +2,8 @@
 #CLOUDBAR_ACTIVE = True
 #CLOUDBAR_LOCATION = 'https://accounts.okeanos.grnet.gr/static/im/cloudbar/'
 #CLOUDBAR_COOKIE_NAME = '_pithos2_a'
-#CLOUDBAR_ACTIVE_SERVICE = 'cloud'
 #CLOUDBAR_SERVICES_URL = 'https://accounts.okeanos.grnet.gr/im/get_services'
 #CLOUDBAR_MENU_URL = 'https://accounts.okeanos.grnet.gr/im/get_menu'
 
+#PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE = 'cloud'
+
index 1a454e1..683ccb6 100644 (file)
@@ -3,7 +3,11 @@ from django.conf import settings
 # !!!!!ATTENTION!!!!!
 # loginUrl MUST end at "next=". You should not give the value of the next
 # parameter. It will be determined automatically
-LOGIN_URL = getattr(settings, 'PITHOS_UI_LOGIN_URL', 'https://accounts.okeanos.grnet.gr/im/login?next=')
-FEEDBACK_URL = getattr(settings, 'PITHOS_UI_FEEDBACK_URL', 'https://accounts.okeanos.grnet.gr/im/feedback')
-AUTH_COOKIE_NAME = getattr(settings, 'PITHOS_UI_AUTH_COOKIE_NAME', '_pithos2_a')
-
+LOGIN_URL = getattr(settings, 'PITHOS_UI_LOGIN_URL',
+    'https://accounts.okeanos.grnet.gr/im/login?next=')
+FEEDBACK_URL = getattr(settings, 'PITHOS_UI_FEEDBACK_URL',
+    'https://accounts.okeanos.grnet.gr/im/feedback')
+AUTH_COOKIE_NAME = getattr(settings, 'PITHOS_UI_AUTH_COOKIE_NAME',
+    '_pithos2_a')
+CLOUDBAR_ACTIVE_SERVICE = getattr(settings, 'PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE',
+    'pithos')
index f2db004..e0d9911 100644 (file)
@@ -41,5 +41,6 @@ MEDIA_URL = getattr(settings, "PITHOS_WEB_CLIENT_MEDIA_URL", \
 
 def index(request):
     return direct_to_template(request, 'pithos_webclient/index.html', \
-            {'settings': settings, 'MEDIA_URL': MEDIA_URL})
+            {'settings': settings, 'MEDIA_URL': MEDIA_URL,
+             'PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE': settings.CLOUDBAR_ACTIVE_SERVICE})
 
index 9c6c9d8..f08248d 100644 (file)
@@ -248,6 +248,13 @@ def build_gwt(root="../", public_dir="bin/www/gr.grnet.pithos.web.Pithos/"):
     index_data = index_data.replace('\' src=\'', '\' src=\'{{ MEDIA_URL }}pithos_webclient/')
     index_data = index_data.replace('url(', 'url({{ MEDIA_URL }}pithos_webclient/')
 
+    index_data = index_data.replace("{{ CLOUDBAR_CODE }}", """
+            {{ CLOUDBAR_CODE }}
+            <script>
+            var CLOUDBAR_ACTIVE_SERVICE = "{{ PITHOS_UI_CLOUDBAR_ACTIVE_SERVICE }}"
+            </script>
+    """)
+
     ifile = file(index, "w+")
     ifile.write(index_data)
     ifile.close()
index 4b1af12..3b97710 100644 (file)
@@ -168,7 +168,7 @@ public class DeleteFileDialog extends DialogBox {
                                public void execute() {\r
                                        app.updateStatistics();\r
                                }\r
-                       });\r
+                       }, true);\r
         }\r
     }\r
 \r
index 19fbaa1..15528c2 100644 (file)
@@ -170,6 +170,9 @@ public class FileContextMenu extends PopupPanel {
          */
         @Source("gr/grnet/pithos/resources/translate.png")
         ImageResource selectAll();
+        
+        @Source("gr/grnet/pithos/resources/internet.png")
+        ImageResource internet();
     }
 
        public static native String getDate()/*-{
@@ -240,6 +243,7 @@ public class FileContextMenu extends PopupPanel {
                if (isFolderTreeSelected && 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)));
                }
 
index a982390..5209536 100644 (file)
@@ -73,14 +73,10 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
 \r
        protected PermissionsList permList;\r
 \r
-       protected CheckBox readForAll;\r
-       \r
        private HorizontalPanel pathPanel;\r
        \r
        private TextBox path;\r
        \r
-       private Dictionary otherProperties = Dictionary.getDictionary("otherProperties");\r
-       \r
        /**\r
         * An image bundle for this widgets images.\r
         */\r
@@ -162,29 +158,29 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
         permPanel.add(permList);\r
 \r
         HorizontalPanel permButtons = new HorizontalPanel();\r
-        Button add = new Button("Add Group", new ClickHandler() {\r
+        final Button addUser = new Button("Add User", new ClickHandler() {\r
             @Override\r
             public void onClick(ClickEvent event) {\r
-                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);\r
                 dlg.center();\r
                 permList.updatePermissionTable();\r
             }\r
         });\r
-        add.addStyleName("button");\r
-        permButtons.add(add);\r
-        permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
+        addUser.addStyleName("button");\r
+        permButtons.add(addUser);\r
+        permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
-        final Button addUser = new Button("Add User", new ClickHandler() {\r
+        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, true);\r
+                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
                 dlg.center();\r
                 permList.updatePermissionTable();\r
             }\r
         });\r
-        addUser.addStyleName("button");\r
-        permButtons.add(addUser);\r
-        permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);\r
+        add.addStyleName("button");\r
+        permButtons.add(add);\r
+        permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
         permButtons.setSpacing(8);\r
         permButtons.addStyleName("pithos-TabPanelBottom");\r
@@ -195,26 +191,6 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                     "distribute this file and that it does not violate the Terms of Use.", true);\r
         readForAllNote.setStylePrimaryName("pithos-readForAllNote");\r
 \r
-        readForAll = new CheckBox();\r
-        readForAll.setValue(file.isPublished());\r
-        readForAll.addClickHandler(new ClickHandler() {\r
-            @Override\r
-            public void onClick(ClickEvent event) {\r
-               accept();\r
-            }\r
-        });\r
-\r
-        // Only show the read for all permission if the user is the owner.\r
-        if (file.getOwner().equals(app.getUsername())) {\r
-            final HorizontalPanel permForAll = new HorizontalPanel();\r
-            permForAll.add(new Label("Public"));\r
-            permForAll.add(readForAll);\r
-            permForAll.setSpacing(8);\r
-            permForAll.addStyleName("pithos-TabPanelBottom");\r
-            permForAll.add(readForAllNote);\r
-            permPanel.add(permForAll);\r
-        }\r
-\r
         pathPanel = new HorizontalPanel();\r
         pathPanel.setVisible(false);\r
         pathPanel.setWidth("100%");\r
@@ -244,23 +220,19 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                        \r
                        @Override\r
                        public void execute() {\r
-                               showLinkIfPublished();\r
+                               showLinkIfShared();\r
                        }\r
                });\r
         return permPanel;\r
     }\r
 \r
-    void showLinkIfPublished() {\r
+    void showLinkIfShared() {\r
                if (file.isShared()) {\r
                        UrlBuilder b = Window.Location.createUrlBuilder();\r
-                       if (file.isPublished()) {\r
-                               b.setPath(file.getPublicUri());\r
-                               path.setText(b.buildString());\r
-                       }\r
-                       else {\r
-                               b.setPath(app.getApiPath() + file.getOwner() + file.getUri());\r
-                               path.setText(GWT.getModuleBaseURL() + "?goto=" + b.buildString());\r
-                       }\r
+                       b.setPath(app.getApiPath() + file.getOwner() + file.getUri());\r
+                       String href = Window.Location.getHref();\r
+                       boolean hasParameters = href.contains("?");\r
+                       path.setText(href + (hasParameters ? "&" : "?") + "goto=" + b.buildString());\r
                pathPanel.setVisible(true);\r
                }\r
                else {\r
@@ -273,15 +245,11 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
         */\r
        @Override\r
        protected void 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, permList.getPermissions());\r
+        updateMetaData(app.getApiPath(), app.getUsername(), file.getUri() + "?update=", permList.getPermissions());\r
        }\r
 \r
-       protected void updateMetaData(String api, String owner, final String path, final Boolean published, final Map<String, Boolean[]> newPermissions) {\r
-        if (published != null || newPermissions != null) {\r
+       protected void updateMetaData(String api, String owner, final String path, final Map<String, Boolean[]> newPermissions) {\r
+        if (newPermissions != null) {\r
             PostRequest updateFile = new PostRequest(api, owner, path) {\r
                 @Override\r
                 public void onSuccess(Resource result) {\r
@@ -289,14 +257,14 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
 \r
                                                @Override\r
                                                public void onSuccess(File _result) {\r
-                                                       showLinkIfPublished();\r
+                                                       showLinkIfShared();\r
                                    app.updateFolder(file.getParent(), true, new Command() {\r
                                                                \r
                                                                @Override\r
                                                                public void execute() {\r
                                                                        app.updateMySharedRoot();\r
                                                                }\r
-                                                       });\r
+                                                       }, true);\r
                                                }\r
 \r
                                                @Override\r
@@ -329,33 +297,29 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
             };\r
             updateFile.setHeader("X-Auth-Token", app.getToken());\r
             \r
-            if (published != null)\r
-                updateFile.setHeader("X-Object-Public", published.toString());\r
-            if (newPermissions != null) {\r
-                String readPermHeader = "read=";\r
-                String writePermHeader = "write=";\r
-                for (String u : newPermissions.keySet()) {\r
-                    Boolean[] p = newPermissions.get(u);\r
-                    if (p[0] != null && p[0])\r
-                        readPermHeader += u + ",";\r
-                    if (p[1] != null && p[1])\r
-                        writePermHeader += u + ",";\r
-                }\r
-                if (readPermHeader.endsWith("="))\r
-                    readPermHeader = "";\r
-                else if (readPermHeader.endsWith(","))\r
-                    readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);\r
-                if (writePermHeader.endsWith("="))\r
-                    writePermHeader = "";\r
-                else if (writePermHeader.endsWith(","))\r
-                    writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);\r
-                String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;\r
-                if (permHeader.length() == 0)\r
-                    permHeader="~";\r
-                else\r
-                       permHeader = URL.encodePathSegment(permHeader);\r
-                updateFile.setHeader("X-Object-Sharing", permHeader);\r
+            String readPermHeader = "read=";\r
+            String writePermHeader = "write=";\r
+            for (String u : newPermissions.keySet()) {\r
+                Boolean[] p = newPermissions.get(u);\r
+                if (p[0] != null && p[0])\r
+                    readPermHeader += u + ",";\r
+                if (p[1] != null && p[1])\r
+                    writePermHeader += u + ",";\r
             }\r
+            if (readPermHeader.endsWith("="))\r
+                readPermHeader = "";\r
+            else if (readPermHeader.endsWith(","))\r
+                readPermHeader = readPermHeader.substring(0, readPermHeader.length() - 1);\r
+            if (writePermHeader.endsWith("="))\r
+                writePermHeader = "";\r
+            else if (writePermHeader.endsWith(","))\r
+                writePermHeader = writePermHeader.substring(0, writePermHeader.length() - 1);\r
+            String permHeader = readPermHeader +  ((readPermHeader.length()  > 0 && writePermHeader.length() > 0) ?  ";" : "") + writePermHeader;\r
+            if (permHeader.length() == 0)\r
+                permHeader="~";\r
+            else\r
+               permHeader = URL.encodePathSegment(permHeader);\r
+            updateFile.setHeader("X-Object-Sharing", permHeader);\r
             Scheduler.get().scheduleDeferred(updateFile);\r
         }\r
         else\r
@@ -363,10 +327,10 @@ public class FilePermissionsDialog extends AbstractPropertiesDialog {
                                \r
                                @Override\r
                                public void execute() {\r
-                                       if (file.isShared())\r
+                                       if (file.isSharedOrPublished())\r
                                                app.updateMySharedRoot();\r
                                }\r
-                       });\r
+                       }, true);\r
     }\r
 \r
        @Override\r
index 2a7bf50..336a5ee 100644 (file)
@@ -309,7 +309,7 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                                                public void execute() {\r
                                                        app.updateMySharedRoot();\r
                                                }\r
-                                       });\r
+                                       }, true);\r
                 }\r
 \r
                 @Override\r
@@ -340,9 +340,9 @@ public class FilePropertiesDialog extends AbstractPropertiesDialog {
                                \r
                                @Override\r
                                public void execute() {\r
-                                       if (file.isShared())\r
+                                       if (file.isSharedOrPublished())\r
                                                app.updateMySharedRoot();\r
                                }\r
-                       });\r
+                       }, true);\r
     }\r
 }\r
diff --git a/src/gr/grnet/pithos/web/client/FilePublishDialog.java b/src/gr/grnet/pithos/web/client/FilePublishDialog.java
new file mode 100644 (file)
index 0000000..ee96121
--- /dev/null
@@ -0,0 +1,305 @@
+/*\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.File;\r
+import gr.grnet.pithos.web.client.foldertree.Resource;\r
+import gr.grnet.pithos.web.client.rest.HeadRequest;\r
+import gr.grnet.pithos.web.client.rest.PostRequest;\r
+\r
+import java.util.Map;\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.http.client.Response;\r
+import com.google.gwt.http.client.URL;\r
+import com.google.gwt.http.client.UrlBuilder;\r
+import com.google.gwt.i18n.client.Dictionary;\r
+import com.google.gwt.resources.client.ImageResource;\r
+import com.google.gwt.user.client.Command;\r
+import com.google.gwt.user.client.Window;\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.CheckBox;\r
+import com.google.gwt.user.client.ui.FocusPanel;\r
+import com.google.gwt.user.client.ui.HasHorizontalAlignment;\r
+import com.google.gwt.user.client.ui.HorizontalPanel;\r
+import com.google.gwt.user.client.ui.Label;\r
+import com.google.gwt.user.client.ui.TextBox;\r
+import com.google.gwt.user.client.ui.VerticalPanel;\r
+\r
+/**\r
+ * The 'File properties' dialog box implementation.\r
+ *\r
+ */\r
+public class FilePublishDialog extends AbstractPropertiesDialog {\r
+\r
+       protected CheckBox readForAll;\r
+       \r
+       private HorizontalPanel pathPanel;\r
+       \r
+       private TextBox path;\r
+       \r
+       /**\r
+        * An image bundle for this widgets images.\r
+        */\r
+       public interface Images extends MessagePanel.Images {\r
+\r
+               @Source("gr/grnet/pithos/resources/edit_user.png")\r
+               ImageResource permUser();\r
+\r
+               @Source("gr/grnet/pithos/resources/groups22.png")\r
+               ImageResource permGroup();\r
+\r
+               @Source("gr/grnet/pithos/resources/editdelete.png")\r
+               ImageResource delete();\r
+       }\r
+\r
+       final File file;\r
+\r
+    Images images = GWT.create(Images.class);\r
+\r
+       /**\r
+        * The widget's constructor.\r
+        */\r
+       public FilePublishDialog(Pithos _app, File _file) {\r
+        super(_app);\r
+        file = _file;\r
+\r
+               Anchor close = new Anchor();\r
+               close.addStyleName("close");\r
+               close.addClickHandler(new ClickHandler() {\r
+                       \r
+                       @Override\r
+                       public void onClick(ClickEvent event) {\r
+                               hide();\r
+                       }\r
+               });\r
+               // Set the dialog's caption.\r
+               setText("Publish/Un-publish");\r
+               setAnimationEnabled(true);\r
+               setGlassEnabled(true);\r
+               setStyleName("pithos-DialogBox");\r
+\r
+               // Outer contains inner and buttons.\r
+               final VerticalPanel outer = new VerticalPanel();\r
+               outer.add(close);\r
+               final FocusPanel focusPanel = new FocusPanel(outer);\r
+               // Inner contains generalPanel and permPanel.\r
+               inner = new VerticalPanel();\r
+               inner.addStyleName("inner");\r
+\r
+        inner.add(createSharingPanel());\r
+\r
+        outer.add(inner);\r
+\r
+               final Button ok = new Button("Close", new ClickHandler() {\r
+                       @Override\r
+                       public void onClick(ClickEvent event) {\r
+                               closeDialog();\r
+                       }\r
+               });\r
+               ok.addStyleName("button");\r
+\r
+        outer.add(ok);\r
+        outer.setCellHorizontalAlignment(inner, HasHorizontalAlignment.ALIGN_CENTER);\r
+\r
+        focusPanel.setFocus(true);\r
+        setWidget(outer);\r
+       }\r
+\r
+    private VerticalPanel createSharingPanel() {\r
+        VerticalPanel permPanel = new VerticalPanel();\r
+\r
+        final Label readForAllNote = new Label("When this option is enabled, the file will be readable" +\r
+                    " by everyone. By checking this option, you are certifying that you have the right to " +\r
+                    "distribute this file and that it does not violate the Terms of Use.", true);\r
+        readForAllNote.setStylePrimaryName("pithos-readForAllNote");\r
+\r
+        readForAll = new CheckBox();\r
+        readForAll.setValue(file.isPublished());\r
+        readForAll.addClickHandler(new ClickHandler() {\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+               accept();\r
+            }\r
+        });\r
+\r
+        // Only show the read for all permission if the user is the owner.\r
+        if (file.getOwner().equals(app.getUsername())) {\r
+            final HorizontalPanel permForAll = new HorizontalPanel();\r
+            permForAll.add(new Label("Public"));\r
+            permForAll.add(readForAll);\r
+            permForAll.setSpacing(8);\r
+            permForAll.addStyleName("pithos-TabPanelBottom");\r
+            permForAll.add(readForAllNote);\r
+            permPanel.add(permForAll);\r
+        }\r
+\r
+        pathPanel = new HorizontalPanel();\r
+        pathPanel.setVisible(false);\r
+        pathPanel.setWidth("100%");\r
+        pathPanel.setHorizontalAlignment(HasHorizontalAlignment.ALIGN_LEFT);\r
+        pathPanel.add(new Label("Link"));\r
+        pathPanel.setSpacing(8);\r
+        pathPanel.addStyleName("pithos-TabPanelBottom");\r
+\r
+        path = new TextBox();\r
+        path.setWidth("100%");\r
+        path.addClickHandler(new ClickHandler() {\r
+            @Override\r
+            public void onClick(ClickEvent event) {\r
+                Pithos.enableIESelection();\r
+                ((TextBox) event.getSource()).selectAll();\r
+                Pithos.preventIESelection();\r
+            }\r
+        });\r
+        path.setText(Window.Location.getHost() + file.getPublicUri());\r
+        path.setTitle("Use this link for sharing the file via e-mail, IM, etc. (crtl-C/cmd-C to copy to system clipboard)");\r
+        path.setWidth("100%");\r
+        path.setReadOnly(true);\r
+        pathPanel.add(path);\r
+        permPanel.add(pathPanel);\r
+\r
+        Scheduler.get().scheduleDeferred(new Command() {\r
+                       \r
+                       @Override\r
+                       public void execute() {\r
+                               showLinkIfPublished();\r
+                       }\r
+               });\r
+        return permPanel;\r
+    }\r
+\r
+    void showLinkIfPublished() {\r
+               if (file.isPublished()) {\r
+                       UrlBuilder b = Window.Location.createUrlBuilder();\r
+                       b.setPath(file.getPublicUri());\r
+                       path.setText(b.buildString());\r
+               pathPanel.setVisible(true);\r
+               }\r
+               else {\r
+                       pathPanel.setVisible(false);\r
+               }\r
+    }\r
+       /**\r
+        * Accepts any change and updates the file\r
+        *\r
+        */\r
+       @Override\r
+       protected void 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
+       }\r
+\r
+       protected void updateMetaData(String api, String owner, final String path, final Boolean published) {\r
+        if (published != null) {\r
+            PostRequest updateFile = new PostRequest(api, owner, path) {\r
+                @Override\r
+                public void onSuccess(Resource result) {\r
+                       HeadRequest<File> headFile = new HeadRequest<File>(File.class, app.getApiPath(), file.getOwner(), path, file) {\r
+\r
+                                               @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
+                                               }\r
+\r
+                                               @Override\r
+                                               public void onError(Throwable t) {\r
+                                   GWT.log("", t);\r
+                                                       app.setError(t);\r
+                                   app.displayError("System error modifying file:" + t.getMessage());\r
+                                               }\r
+\r
+                                               @Override\r
+                                               protected void onUnauthorized(Response response) {\r
+                                                       app.sessionExpired();\r
+                                               }\r
+                                       };\r
+                                       headFile.setHeader("X-Auth-Token", app.getToken());\r
+                                       Scheduler.get().scheduleDeferred(headFile);\r
+                }\r
+\r
+                @Override\r
+                public void onError(Throwable t) {\r
+                    GWT.log("", t);\r
+                                       app.setError(t);\r
+                    app.displayError("System error modifying file:" + t.getMessage());\r
+                }\r
+\r
+                               @Override\r
+                               protected void onUnauthorized(Response response) {\r
+                                       app.sessionExpired();\r
+                               }\r
+            };\r
+            updateFile.setHeader("X-Auth-Token", app.getToken());\r
+            updateFile.setHeader("X-Object-Public", published.toString());\r
+            Scheduler.get().scheduleDeferred(updateFile);\r
+        }\r
+        else\r
+            app.updateFolder(file.getParent(), true, new Command() {\r
+                               \r
+                               @Override\r
+                               public void execute() {\r
+                                       if (file.isSharedOrPublished())\r
+                                               app.updateMySharedRoot();\r
+                               }\r
+                       }, 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("keydown") && evt.getKeyCode() == KeyCodes.KEY_ENTER)\r
+                               closeDialog();\r
+       }\r
+}\r
index 8ce3a26..c2acca2 100644 (file)
@@ -154,7 +154,7 @@ public class FileUploadDialog extends DialogBox {
                                public void execute() {
                                        app.updateStatistics();
                                }
-                       });
+                       }, true);
                else
                        app.updateOtherSharedFolder(folder, true);
        }
index 669ad6a..e79007c 100644 (file)
@@ -193,9 +193,9 @@ public class FileVersionsDialog extends AbstractPropertiesDialog {
                        \r
                        @Override\r
                        public void execute() {\r
-                               if (file.isShared())\r
+                               if (file.isSharedOrPublished())\r
                                        app.updateMySharedRoot();\r
                        }\r
-               });\r
+               }, true);\r
        }\r
 }\r
index 9e3e0d8..47bd080 100644 (file)
@@ -123,27 +123,28 @@ public class FolderPermissionsDialog extends DialogBox {
         permPanel.add(permList);\r
 \r
         HorizontalPanel permButtons = new HorizontalPanel();\r
-        Button add = new Button("Add Group", new ClickHandler() {\r
+        Button addUser = new Button("Add User", new ClickHandler() {\r
             @Override\r
             public void onClick(ClickEvent event) {\r
-                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
+                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, true);\r
                 dlg.center();\r
             }\r
         });\r
-        add.addStyleName("button");\r
-        permButtons.add(add);\r
-        permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
+        addUser.addStyleName("button");\r
+        permButtons.add(addUser);\r
+        permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);\r
 \r
-        Button addUser = new Button("Add User", new ClickHandler() {\r
+        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, true);\r
+                PermissionsAddDialog dlg = new PermissionsAddDialog(app, app.getAccount().getGroups(), permList, false);\r
                 dlg.center();\r
             }\r
         });\r
-        addUser.addStyleName("button");\r
-        permButtons.add(addUser);\r
-        permButtons.setCellHorizontalAlignment(addUser, HasHorizontalAlignment.ALIGN_CENTER);\r
+        add.addStyleName("button");\r
+        permButtons.add(add);\r
+        permButtons.setCellHorizontalAlignment(add, HasHorizontalAlignment.ALIGN_CENTER);\r
+\r
         permButtons.setSpacing(8);\r
         permPanel.add(permButtons);\r
 \r
@@ -258,7 +259,7 @@ public class FolderPermissionsDialog extends DialogBox {
                                                public void execute() {\r
                                                        app.updateMySharedRoot();\r
                                                }\r
-                                       });\r
+                                       }, true);\r
                 }\r
 \r
                 @Override\r
@@ -344,6 +345,6 @@ public class FolderPermissionsDialog extends DialogBox {
                                public void execute() {\r
                                        app.updateMySharedRoot();\r
                                }\r
-                       });\r
+                       }, true);\r
     }\r
 }\r
index ed8828f..aa5116d 100644 (file)
@@ -249,7 +249,7 @@ public class FolderPropertiesDialog extends DialogBox {
                                        public void execute() {\r
                                                app.updateStatistics();\r
                                        }\r
-                               });\r
+                               }, true);\r
             }\r
 \r
             @Override\r
@@ -313,7 +313,7 @@ public class FolderPropertiesDialog extends DialogBox {
                                                                public void execute() {\r
                                                                        app.updateMySharedRoot();\r
                                                                }\r
-                                                       });\r
+                                                       }, true);\r
                                                                                }\r
                                                                        });\r
                                 }\r
@@ -351,6 +351,6 @@ public class FolderPropertiesDialog extends DialogBox {
                        public void execute() {\r
                                app.updateMySharedRoot();\r
                        }\r
-               });\r
+               }, true);\r
        }\r
 }\r
index 19c871e..5c733ba 100644 (file)
@@ -50,6 +50,7 @@ import com.google.gwt.user.client.ui.DialogBox;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.ListBox;
+import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.TextBox;
 import com.google.gwt.user.client.ui.VerticalPanel;
 
@@ -59,9 +60,9 @@ public class PermissionsAddDialog extends DialogBox {
 
        private ListBox groupBox = new ListBox();
 
-       private CheckBox read = new CheckBox();
+       private RadioButton read = new RadioButton("permissions");
 
-       private CheckBox write = new CheckBox();
+       private RadioButton write = new RadioButton("permissions");
 
        private PermissionsList permList;
 
@@ -94,8 +95,8 @@ public class PermissionsAddDialog extends DialogBox {
 
         final FlexTable permTable = new FlexTable();
         permTable.setText(0, 0, "Users/Groups");
-        permTable.setText(0, 1, "Read");
-        permTable.setText(0, 2, "Write");
+        permTable.setText(0, 1, "Read Only");
+        permTable.setText(0, 2, "Read/Write");
         permTable.getFlexCellFormatter().setStyleName(0, 0, "props-toplabels");
         permTable.getFlexCellFormatter().setStyleName(0, 1, "props-toplabels");
         permTable.getFlexCellFormatter().setStyleName(0, 2, "props-toplabels");
@@ -108,7 +109,8 @@ public class PermissionsAddDialog extends DialogBox {
                 groupBox.addItem(group.getName(), group.getName());
             permTable.setWidget(1, 0, groupBox);
         }
-
+                
+        read.setValue(true);
         permTable.setWidget(1, 1, read);
         permTable.setWidget(1, 2, write);
 
index 0b33341..1345efb 100644 (file)
@@ -50,6 +50,7 @@ import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlexTable;
 import com.google.gwt.user.client.ui.HasHorizontalAlignment;
 import com.google.gwt.user.client.ui.PushButton;
+import com.google.gwt.user.client.ui.RadioButton;
 import com.google.gwt.user.client.ui.VerticalPanel;
 
 
@@ -77,8 +78,8 @@ public class PermissionsList extends Composite {
                owner = theOwner;
                permissions =  new HashMap<String, Boolean[]>(thePermissions);
                permTable.setText(0, 0, "Users/Groups");
-               permTable.setText(0, 1, "Read");
-               permTable.setText(0, 2, "Write");
+               permTable.setText(0, 1, "Read Only");
+               permTable.setText(0, 2, "Read/Write");
                permTable.setText(0, 3, "");
                permTable.getFlexCellFormatter().setStyleName(0, 0, "props-toplabels");
                permTable.getFlexCellFormatter().setStyleName(0, 1, "props-toplabels");
@@ -130,12 +131,12 @@ public class PermissionsList extends Composite {
             Boolean readP = userPerms[0];
             Boolean writeP = userPerms[1];
 
-                       CheckBox read = new CheckBox();
+                       RadioButton read = new RadioButton("permissions" + i);
                        read.setValue(readP != null ? readP : false);
             permTable.setWidget(i, 1, read);
             permTable.getFlexCellFormatter().setHorizontalAlignment(i, 1, HasHorizontalAlignment.ALIGN_CENTER);
 
-            CheckBox write = new CheckBox();
+            RadioButton write = new RadioButton("permissions" + i);
             write.setValue(writeP != null ? writeP : false);
             permTable.setWidget(i, 2, write);
             permTable.getFlexCellFormatter().setHorizontalAlignment(i, 2, HasHorizontalAlignment.ALIGN_CENTER);
@@ -146,6 +147,7 @@ public class PermissionsList extends Composite {
                     public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) {
                         Boolean[] ps = permissions.get(user);
                         ps[0] = booleanValueChangeEvent.getValue();
+                        ps[1] = !booleanValueChangeEvent.getValue();
                         hasChanges = true;
                         if (changePermissionsCallback != null)
                                changePermissionsCallback.execute();
@@ -155,6 +157,7 @@ public class PermissionsList extends Composite {
                     @Override
                     public void onValueChange(ValueChangeEvent<Boolean> booleanValueChangeEvent) {
                         Boolean[] ps = permissions.get(user);
+                        ps[0] = !booleanValueChangeEvent.getValue();
                         ps[1] = booleanValueChangeEvent.getValue();
                         hasChanges = true;
                         if (changePermissionsCallback != null)
index 2978ca3..522e111 100644 (file)
@@ -132,8 +132,8 @@ public class Pithos implements EntryPoint, ResizeHandler {
         return account;
     }
 
-    public void updateFolder(Folder f, boolean showfiles, Command callback) {
-        folderTreeView.updateFolder(f, showfiles, callback);
+    public void updateFolder(Folder f, boolean showfiles, Command callback, final boolean openParent) {
+        folderTreeView.updateFolder(f, showfiles, callback, openParent);
     }
 
     public void updateGroupNode(Group group) {
@@ -345,7 +345,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
                                public void execute() {
                                        updateStatistics();
                                }
-                       });
+                       }, true);
                        showRelevantToolbarButtons();
                 }
                                else {
@@ -472,7 +472,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
                                Folder f = getSelection();
                                if (f != null) {
                                        if (getSelectedTree().equals(folderTreeView))
-                                               updateFolder(f, true, null);
+                                               updateFolder(f, true, null, false);
                                        else if (getSelectedTree().equals(mysharedTreeView))
                                                updateSharedFolder(f, true);
                                }
@@ -912,11 +912,12 @@ public class Pithos implements EntryPoint, ResizeHandler {
                                                
                                                @Override
                                                public void execute() {
+                                                       folderTreeSelectionModel.setSelected(folder.getParent(), true);
                                                        updateStatistics();
                                                        if (callback != null)
                                                                callback.execute();
                                                }
-                                       });
+                                       }, true);
                 }
 
                 @Override
@@ -1072,7 +1073,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
        }
 
        public void updateTrash(boolean showFiles, Command callback) {
-               updateFolder(trash, showFiles, callback);
+               updateFolder(trash, showFiles, callback, true);
        }
 
        public void updateGroupsNode() {
@@ -1115,7 +1116,7 @@ public class Pithos implements EntryPoint, ResizeHandler {
        }
 
        public void updateRootFolder(Command callback) {
-               updateFolder(account.getPithos(), false, callback);
+               updateFolder(account.getPithos(), false, callback, true);
        }
 
        void createMySharedTree() {
index 63bb5cb..35ffe88 100644 (file)
@@ -128,7 +128,7 @@ public class Toolbar extends Composite {
                                        public void execute() {
                                                app.updateStatistics();
                                        }
-                               });
+                               }, true);
                        }
                });
         toolbar.add(refreshButton);
index febfd67..e51776e 100644 (file)
@@ -178,6 +178,7 @@ public class ToolsMenu extends PopupPanel {
                                        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)));
                                                empty = false;
                                        }
index 6ae2669..e964a24 100644 (file)
@@ -86,7 +86,7 @@ public class PasteCommand implements Command {
                                                        public void execute() {
                                                                app.updateStatistics();
                                                        }
-                                               });
+                                               }, true);
                     }
                 });
             }
@@ -96,7 +96,7 @@ public class PasteCommand implements Command {
                     public void execute() {
                         app.getClipboard().clear();
                         app.deleteFolder(tobeCopied, null);
-                        app.updateFolder(folder, true, null);
+                        app.updateFolder(folder, true, null, true);
                     }
                 });
             }
@@ -116,7 +116,7 @@ public class PasteCommand implements Command {
                                                        public void execute() {
                                                                app.updateStatistics();
                                                        }
-                                               });
+                                               }, true);
                     }
                 });
             }
@@ -125,7 +125,7 @@ public class PasteCommand implements Command {
                     @Override
                     public void execute() {
                         app.getClipboard().clear();
-                        app.updateFolder(folder, true, null);
+                        app.updateFolder(folder, true, null, true);
                     }
                 });
             }
index c4bdf83..7e40560 100644 (file)
@@ -36,6 +36,7 @@ package gr.grnet.pithos.web.client.commands;
 
 import gr.grnet.pithos.web.client.FilePermissionsDialog;
 import gr.grnet.pithos.web.client.FilePropertiesDialog;
+import gr.grnet.pithos.web.client.FilePublishDialog;
 import gr.grnet.pithos.web.client.FileVersionsDialog;
 import gr.grnet.pithos.web.client.FilesPropertiesDialog;
 import gr.grnet.pithos.web.client.FolderPermissionsDialog;
@@ -59,6 +60,7 @@ public class PropertiesCommand implements Command {
        public static final int PROPERTIES = 0;
        public static final int PERMISSIONS = 1;
        public static final int VERSIONS = 2;
+       public static final int PUBLISH = 3;
 
        private PopupPanel containerPanel;
 
@@ -139,6 +141,16 @@ public class PropertiesCommand implements Command {
                                FileVersionsDialog dlg2 = new FileVersionsDialog(app, files.get(0));
                                dlg2.center();
                                                break;
+                                       case PUBLISH:
+                               app.scheduleFileHeadCommand(f, new Command() {
+                                                       
+                                                       @Override
+                                                       public void execute() {
+                                                               FilePublishDialog dlg = new FilePublishDialog(app, f);
+                                                               dlg.center();
+                                                       }
+                                               });
+                                               break;
                                        default:
                                                break;
                                }
index 6e5d14e..a35f9a8 100644 (file)
@@ -68,6 +68,6 @@ public class RefreshCommand implements Command {
                        public void execute() {
                                app.updateStatistics();
                        }
-               });
+               }, true);
        }
 }
index c5bda2e..bf25555 100644 (file)
@@ -85,9 +85,9 @@ public class RestoreTrashCommand implements Command {
                                                
                                                @Override
                                                public void execute() {
-                                                       app.updateFolder(app.getAccount().getPithos(), false, null);
+                                                       app.updateFolder(app.getAccount().getPithos(), false, null, true);
                                                }
-                                       });
+                                       }, true);
                 }
             });
         }
@@ -100,9 +100,9 @@ public class RestoreTrashCommand implements Command {
                                                
                                                @Override
                                                public void execute() {
-                                                       app.updateFolder(app.getAccount().getPithos(), false, null);
+                                                       app.updateFolder(app.getAccount().getPithos(), false, null, true);
                                                }
-                                       });
+                                       }, true);
                 }
             });
 
index 8d7ed28..90f159b 100644 (file)
@@ -87,7 +87,7 @@ public class ToTrashCommand implements Command{
                                                public void execute() {
                                                        app.updateTrash(false, null);
                                                }
-                                       });
+                                       }, true);
                 }
             });
         }
@@ -102,7 +102,7 @@ public class ToTrashCommand implements Command{
                                                public void execute() {
                                                        app.updateTrash(false, null);
                                                }
-                                       });
+                                       }, true);
                 }
             });
 
index e1cee32..01a3215 100644 (file)
@@ -139,9 +139,13 @@ public class File extends Resource {
         return nf.format(Double.valueOf(bytes)/(1024 * 1024 * 1024)) + " GB";
     }
 
-    public boolean isShared() {
+    public boolean isSharedOrPublished() {
         return !permissions.isEmpty() || published;
     }
+    
+    public boolean isShared() {
+       return !permissions.isEmpty();
+    }
 
     public void populate(Folder _parent, JSONObject o, String _owner, String _container) {
         this.parent = _parent;
index f0b2e37..08d9e74 100644 (file)
@@ -175,7 +175,7 @@ public class FolderTreeView extends Composite implements TreeView {
        return model.getSelection();
     }
 
-    public void updateFolder(Folder folder, boolean showfiles, Command callback) {
-        model.updateFolder(folder, showfiles, callback);
+    public void updateFolder(Folder folder, boolean showfiles, Command callback, final boolean openParent) {
+        model.updateFolder(folder, showfiles, callback, openParent);
     }
 }
index 6f35350..843f14f 100644 (file)
@@ -210,7 +210,7 @@ public class FolderTreeViewModel implements TreeViewModel {
         return selectionModel.getSelectedObject();
     }
 
-    public void updateFolder(final Folder folder, boolean showfiles, final Command callback) {
+    public void updateFolder(final Folder folder, boolean showfiles, final Command callback, final boolean openParent) {
         if (dataProviderMap.get(folder) == null) {
             dataProviderMap.put(folder, new ListDataProvider<Folder>());
         }
@@ -219,7 +219,8 @@ public class FolderTreeViewModel implements TreeViewModel {
                        
                        @Override
                        public void execute() {
-                               app.getFolderTreeView().openFolder(folder);
+                               if (openParent)
+                                       app.getFolderTreeView().openFolder(folder);
                                if (callback != null)
                                        callback.execute();
                        }
index ae4c15e..b0c9476 100644 (file)
@@ -160,6 +160,5 @@ public class MysharedTreeView extends Composite implements TreeView {
                TreeNode root = ((CellTree) getWidget()).getRootTreeNode();
                root.setChildOpen(0, true);
                root.setChildOpen(0, false);
-               model.fetchSharedFiles(false);
        }
 }
index d2640fd..8b98bc2 100644 (file)
@@ -37,6 +37,7 @@ package gr.grnet.pithos.web.client.mysharedtree;
 
 import gr.grnet.pithos.web.client.FolderContextMenu;
 import gr.grnet.pithos.web.client.Pithos;
+import gr.grnet.pithos.web.client.foldertree.AccountResource;
 import gr.grnet.pithos.web.client.foldertree.File;
 import gr.grnet.pithos.web.client.foldertree.Folder;
 import gr.grnet.pithos.web.client.foldertree.FolderTreeView;
@@ -108,8 +109,6 @@ public class MysharedTreeViewModel implements TreeViewModel {
 
     private Map<Folder, ListDataProvider<Folder>> dataProviderMap = new HashMap<Folder, ListDataProvider<Folder>>();
     
-    protected Set<File> sharedFiles = new HashSet<File>();
-
     protected SingleSelectionModel<Folder> selectionModel;
 
     public MysharedTreeViewModel(Pithos _app, SingleSelectionModel<Folder> selectionModel) {
@@ -122,26 +121,6 @@ public class MysharedTreeViewModel implements TreeViewModel {
         if (value == null) {
             ListDataProvider<String> rootDataProvider = new ListDataProvider<String>();
             rootDataProvider.getList().add("Shared by me");
-            final SingleSelectionModel<String> selectionModel2 = new SingleSelectionModel<String>();
-            selectionModel2.addSelectionChangeHandler(new Handler() {
-
-                @Override
-                public void onSelectionChange(SelectionChangeEvent event) {
-                    if (selectionModel2.getSelectedObject() != null) {
-                       app.deselectOthers(app.getMySharedTreeView(), selectionModel2);
-                       app.applyPermissions(null);
-                       fetchSharedFiles(true);
-                                       app.showRelevantToolbarButtons();
-                    }
-                               else {
-                                       if (app.getSelectedTree().equals(app.getMySharedTreeView()))
-                                               app.setSelectedTree(null);
-                                       if (app.getSelectedTree() == null)
-                                               app.showRelevantToolbarButtons();
-                               }
-                }
-            });
-            app.addSelectionModel(selectionModel2);
             return new DefaultNodeInfo<String>(rootDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
                 @Override
                 public SafeHtml render(String object) {
@@ -156,7 +135,7 @@ public class MysharedTreeViewModel implements TreeViewModel {
                     builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
                     builder.append(MysharedTreeView.Templates.INSTANCE.nameSpan(object));
                 }
-            }),  selectionModel2, null);
+            }),  null, null);
         }
         else if (value instanceof String) {
                fetchSharedContainers(null);
@@ -173,37 +152,47 @@ public class MysharedTreeViewModel implements TreeViewModel {
         }
     }
 
-       protected void fetchSharedFiles(final boolean showFiles) {
-               sharedFiles.clear();
-       final List<Folder> containers = app.getAccount().getContainers();
-       final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
-       Iterator<Folder> iter = containers.iterator();
-       fetchFolder(iter, tempProvider, new Command() {
-                       
-                       @Override
-                       public void execute() {
-                               firstLevelDataProvider.getList().clear();
-                               firstLevelDataProvider.getList().addAll(tempProvider.getList());
-                               if (showFiles)
-                                       app.showFiles(sharedFiles);
-                       }
-               });
-       }
-
        private void fetchSharedContainers(final Command callback) {
-       final List<Folder> containers = app.getAccount().getContainers();
-       final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
-       Iterator<Folder> iter = containers.listIterator();
-       fetchFolder(iter, tempProvider, new Command() {
-                       
+        String path = "?format=json&shared=";
+        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();
+                                       }
+                               });
+            }
+
+            @Override
+            public void onError(Throwable t) {
+                GWT.log("Error getting account", t);
+                               app.setError(t);
+                if (t instanceof RestException)
+                    app.displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
+                else
+                    app.displayError("System error fetching user data: " + t.getMessage());
+            }
+
                        @Override
-                       public void execute() {
-                               firstLevelDataProvider.getList().clear();
-                               firstLevelDataProvider.getList().addAll(tempProvider.getList());
-                               if (callback != null)
-                                       callback.execute();
+                       protected void onUnauthorized(Response response) {
+                               app.sessionExpired();
                        }
-               });
+        };
+        getAccount.setHeader("X-Auth-Token", app.getToken());
+        Scheduler.get().scheduleDeferred(getAccount);
        }
 
        @Override
@@ -223,32 +212,15 @@ public class MysharedTreeViewModel implements TreeViewModel {
                $wnd.console.log(msg);
        }-*/;
 
-    protected void fetchFolder(final Iterator<Folder> iter, final ListDataProvider<Folder> dataProvider, final Command callback) {
+    protected void fetchFolder(final Iterator<Folder> iter, final Command callback) {
         if (iter.hasNext()) {
             final Folder f = iter.next();
 
-            String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
+            String path = "/" + f.getContainer() + "?format=json&shared=&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
             GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), f.getOwner(), path, f) {
                 @Override
                 public void onSuccess(Folder _result) {
-                       if (!_result.isShared()) {
-                               for (File file : _result.getFiles()) {
-                                       if (file.isShared())
-                                               sharedFiles.add(file);
-                               }
-                               Iterator<Folder> iter2 = new ArrayList<Folder>(result.getSubfolders()).listIterator();
-                               fetchFolder(iter2, dataProvider, new Command() {
-                                                       
-                                                       @Override
-                                                       public void execute() {
-                                           fetchFolder(iter, dataProvider, callback);
-                                                       }
-                                               });
-                       }
-                       else {
-                               dataProvider.getList().add(_result);
-                           fetchFolder(iter, dataProvider, callback);
-                       }
+                    fetchFolder(iter, callback);
                 }
 
                 @Override
@@ -286,14 +258,14 @@ public class MysharedTreeViewModel implements TreeViewModel {
     }
 
     public void fetchFolder(final Folder f, final ListDataProvider<Folder> dataProvider, final boolean showfiles) {
-        String path = "/" + f.getContainer() + "?format=json&delimiter=/&prefix=" + URL.encodeQueryString(f.getPrefix());
+        String path = "/" + f.getContainer() + "?format=json&shared=&delimiter=/&prefix=" + 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 = _result.getSubfolders().iterator();
-                fetchFolder(iter, dataProvider, new Command() {
+                Iterator<Folder> iter = new ArrayList<Folder>(_result.getSubfolders()).listIterator();
+                fetchFolder(iter, new Command() {
                     @Override
                     public void execute() {
                         dataProvider.getList().clear();
index a958003..63c2426 100644 (file)
@@ -111,8 +111,6 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
     protected Map<String, ListDataProvider<Folder>> userDataProviderMap = new HashMap<String, ListDataProvider<Folder>>();
     private Map<Folder, ListDataProvider<Folder>> dataProviderMap = new HashMap<Folder, ListDataProvider<Folder>>();
     
-    protected Map<String, Set<File>> sharedFiles = new HashMap<String, Set<File>>();
-
     protected SingleSelectionModel<Folder> selectionModel;
 
     public OtherSharedTreeViewModel(Pithos _app, SingleSelectionModel<Folder> selectionModel) {
@@ -124,26 +122,6 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
     public <T> NodeInfo<?> getNodeInfo(T value) {
         if (value == null) {
             rootDataProvider.getList().add(treeTitle);
-            final SingleSelectionModel<String> selectionModel2 = new SingleSelectionModel<String>();
-            selectionModel2.addSelectionChangeHandler(new Handler() {
-
-                @Override
-                public void onSelectionChange(SelectionChangeEvent event) {
-                    if (selectionModel2.getSelectedObject() != null) {
-                       app.deselectOthers(app.getOtherSharedTreeView(), selectionModel2);
-                       app.applyPermissions(null);
-                       app.showFiles(new HashSet<File>());
-                                       app.showRelevantToolbarButtons();
-                    }
-                               else {
-                                       if (app.getSelectedTree().equals(app.getOtherSharedTreeView()))
-                                               app.setSelectedTree(null);
-                                       if (app.getSelectedTree() == null)
-                                               app.showRelevantToolbarButtons();
-                               }
-                }
-            });
-            app.addSelectionModel(selectionModel2);
             return new DefaultNodeInfo<String>(rootDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
                 @Override
                 public SafeHtml render(String object) {
@@ -158,35 +136,11 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
                     builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
                     builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
                 }
-            }),  selectionModel2, null);
+            }),  null, null);
         }
         else if (value instanceof String) {
                if (value.equals(treeTitle)) {
                        fetchSharingUsers(null);
-                   final SingleSelectionModel<String> selectionModel3 = new SingleSelectionModel<String>();
-                   selectionModel3.addSelectionChangeHandler(new Handler() {
-
-                       @Override
-                       public void onSelectionChange(SelectionChangeEvent event) {
-                           if (selectionModel3.getSelectedObject() != null) {
-                               app.deselectOthers(app.getOtherSharedTreeView(), selectionModel3);
-                               app.applyPermissions(null);
-                               String username = selectionModel3.getSelectedObject();
-                                       if (userDataProviderMap.get(username) == null) {
-                                               userDataProviderMap.put(username, new ListDataProvider<Folder>());
-                                       }
-                               fetchSharedFiles(username, userDataProviderMap.get(username));
-                                               app.showRelevantToolbarButtons();
-                           }
-                                       else {
-                                               if (app.getSelectedTree().equals(app.getOtherSharedTreeView()))
-                                                       app.setSelectedTree(null);
-                                               if (app.getSelectedTree() == null)
-                                                       app.showRelevantToolbarButtons();
-                                       }
-                       }
-                   });
-                   app.addSelectionModel(selectionModel3);
                    return new DefaultNodeInfo<String>(userLevelDataProvider, new TextCell(new SafeHtmlRenderer<String>() {
 
                                        @Override
@@ -202,7 +156,7 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
                            builder.appendHtmlConstant(html).appendHtmlConstant("&nbsp;");
                            builder.append(OtherSharedTreeView.Templates.INSTANCE.nameSpan(object));
                                        }
-                               }), selectionModel3, null);
+                               }), null, null);
                }
                        String username = (String) value;
                        if (userDataProviderMap.get(username) == null) {
@@ -229,9 +183,6 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
             public void onSuccess(final SharingUsers _result) {
                 userLevelDataProvider.getList().clear();
                 userLevelDataProvider.getList().addAll(_result.getUsers());
-                for (String name : _result.getUsers()) {
-                       sharedFiles.put(name, new HashSet<File>());
-                }
                 Iterator<String> iter = _result.getUsers().iterator();
                 fetchSharedContainers(iter, callback);
             }
@@ -332,44 +283,6 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
                Scheduler.get().scheduleDeferred(getUserSharedContainers);
        }
 
-       protected void fetchSharedFiles(final String username, final ListDataProvider<Folder> dataProvider) {
-               GetRequest<AccountResource> getUserSharedContainers = new GetRequest<AccountResource>(AccountResource.class, app.getApiPath(), username, "?format=json") {
-
-                       @Override
-                       public void onSuccess(AccountResource _result) {
-                       final ListDataProvider<Folder> tempProvider = new ListDataProvider<Folder>();
-                               Iterator<Folder> iter = _result.getContainers().iterator();
-                               sharedFiles.get(username).clear();
-                               fetchFolder(username, iter, tempProvider, new Command() {
-                                       
-                                       @Override
-                                       public void execute() {
-                                               dataProvider.getList().clear();
-                                               dataProvider.getList().addAll(tempProvider.getList());
-                                               app.showFiles(sharedFiles.get(username));
-                                       }
-                               });
-                       }
-
-                       @Override
-                       public void onError(Throwable t) {
-                GWT.log("Error getting account", t);
-                               app.setError(t);
-                if (t instanceof RestException)
-                    app.displayError("Error getting account: " + ((RestException) t).getHttpStatusText());
-                else
-                    app.displayError("System error fetching user data: " + t.getMessage());
-                       }
-
-                       @Override
-                       protected void onUnauthorized(Response response) {
-                               app.sessionExpired();
-                       }
-               };
-               getUserSharedContainers.setHeader("X-Auth-Token", app.getToken());
-               Scheduler.get().scheduleDeferred(getUserSharedContainers);
-       }
-
        protected void fetchFolder(final String username, final Iterator<Folder> iter, final ListDataProvider<Folder> dataProvider, final Command callback) {
         if (iter.hasNext()) {
             final Folder f = iter.next();
@@ -378,24 +291,8 @@ public class OtherSharedTreeViewModel implements TreeViewModel {
             GetRequest<Folder> getFolder = new GetRequest<Folder>(Folder.class, app.getApiPath(), username, path, f) {
                 @Override
                 public void onSuccess(Folder _result) {
-                       if (!_result.isShared() && !_result.isContainer()) {
-                               for (File file : _result.getFiles()) {
-                                       if (file.isShared())
-                                               sharedFiles.get(username).add(file);
-                               }
-                               Iterator<Folder> iter2 = _result.getSubfolders().iterator();
-                               fetchFolder(username, iter2, dataProvider, new Command() {
-                                                       
-                                                       @Override
-                                                       public void execute() {
-                                           fetchFolder(username, iter, dataProvider, callback);
-                                                       }
-                                               });
-                       }
-                       else {
-                               dataProvider.getList().add(_result);
-                           fetchFolder(username, iter, dataProvider, callback);
-                       }
+                               dataProvider.getList().add(_result);
+                    fetchFolder(username, iter, dataProvider, callback);
                 }
 
                 @Override