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