From 7619df4ca8b32dad64825bdfaa3089e0a290b629 Mon Sep 17 00:00:00 2001 From: Francesco Mangiacrapa Date: Thu, 21 Apr 2016 08:37:31 +0000 Subject: [PATCH] git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/portlets/user/workspace-explorer-app@128209 82a268e6-3cf1-43bd-a215-b396298e98cf --- .classpath | 37 + .project | 47 ++ .settings/.jsdtscope | 5 + .../com.google.appengine.eclipse.core.prefs | 2 + .settings/com.google.gdt.eclipse.core.prefs | 6 + .settings/com.google.gwt.eclipse.core.prefs | 2 + .settings/org.eclipse.core.resources.prefs | 6 + .settings/org.eclipse.jdt.core.prefs | 8 + .settings/org.eclipse.wst.common.component | 10 + ....eclipse.wst.common.project.facet.core.xml | 5 + .settings/org.eclipse.wst.validation.prefs | 2 + distro/LICENSE | 1 + distro/README | 60 ++ distro/changelog.xml | 6 + distro/descriptor.xml | 32 + distro/profile.xml | 25 + pom.xml | 319 ++++++++ .../WorkspaceExplorerApp.gwt.xml | 29 + .../client/ItemComparatorUtility.java | 89 +++ .../client/NewBrowserWindow.java | 51 ++ .../client/SortByContextMenu.java | 58 ++ .../workspaceexplorerapp/client/Util.java | 144 ++++ .../client/WorkspaceExplorerApp.java | 98 +++ .../client/WorkspaceExplorerAppConstants.java | 41 ++ .../WorkspaceExplorerAppController.java | 140 ++++ .../client/WorkspaceExplorerAppMainPanel.java | 157 ++++ .../WorkspaceExplorerAppMainPanel.ui.xml | 75 ++ .../client/WorkspaceExplorerAppPanel.java | 33 + .../client/WorkspaceExplorerFoooterPanel.java | 51 ++ .../WorkspaceExplorerFoooterPanel.ui.xml | 14 + .../WorkspaceExplorerSelectNotification.java | 94 +++ .../WorkspaceResourcesExplorerPanel.java | 510 +++++++++++++ .../client/download/DownloadType.java | 18 + .../RequestBuilderWorkspaceValidateItem.java | 121 ++++ .../client/download/WindowOpenParameter.java | 91 +++ .../client/event/BreadcrumbClickEvent.java | 61 ++ .../event/BreadcrumbClickEventHandler.java | 20 + .../client/event/BreadcrumbInitEvent.java | 61 ++ .../event/BreadcrumbInitEventHandler.java | 20 + .../client/event/ClickItemEvent.java | 54 ++ .../client/event/ClickItemEventHandler.java | 20 + .../client/event/CreateFolderClickEvent.java | 36 + .../event/CreateFolderClickEventHandler.java | 20 + .../client/event/DownloadItemEvent.java | 63 ++ .../event/DownloadItemEventHandler.java | 19 + .../client/event/LoadFolderEvent.java | 61 ++ .../client/event/LoadFolderEventHandler.java | 16 + .../event/LoadMySpecialFolderEvent.java | 35 + .../LoadMySpecialFolderEventHandler.java | 21 + .../client/event/LoadRootEvent.java | 33 + .../client/event/LoadRootEventHandler.java | 20 + .../client/event/OrderDataByEvent.java | 51 ++ .../client/event/OrderDataByEventHandler.java | 24 + .../client/event/RightClickItemEvent.java | 81 +++ .../event/RightClickItemEventHandler.java | 21 + .../client/event/RootLoadedEvent.java | 45 ++ .../client/event/RootLoadedEventHandler.java | 23 + .../client/grid/AbstractItemsCellTable.java | 196 +++++ .../client/grid/DisplayField.java | 84 +++ .../client/grid/ItemsTable.java | 399 ++++++++++ .../client/grid/MaterialIconCell.java | 61 ++ .../client/grid/MenuMoreOptionsOnItem.java | 93 +++ .../client/grid/MenuMoreOptionsOnItem.ui.xml | 19 + .../resources/WorkspaceExplorerAppCss.css | 7 + .../resources/WorkspaceExplorerAppCss.java | 23 + .../resources/WorkspaceExplorerResources.java | 36 + .../WorkspaceLightTreeResources.java | 245 +++++++ .../client/resources/_32/folder.png | Bin 0 -> 1250 bytes .../client/resources/_32/groups_folder.png | Bin 0 -> 1730 bytes .../client/resources/ajax-loader.gif | Bin 0 -> 673 bytes .../client/resources/aquamaps.png | Bin 0 -> 980 bytes .../client/resources/document.png | Bin 0 -> 294 bytes .../client/resources/error.png | Bin 0 -> 666 bytes .../client/resources/external_file.png | Bin 0 -> 464 bytes .../client/resources/external_image.gif | Bin 0 -> 997 bytes .../client/resources/external_pdf.gif | Bin 0 -> 980 bytes .../resources/external_resource_link.png | Bin 0 -> 855 bytes .../client/resources/external_url.png | Bin 0 -> 343 bytes .../client/resources/folder.png | Bin 0 -> 537 bytes .../client/resources/gcubeItem.jpeg | Bin 0 -> 905 bytes .../client/resources/icon-unknown.gif | Bin 0 -> 376 bytes .../client/resources/image_document.png | Bin 0 -> 650 bytes .../client/resources/invalid_name.gif | Bin 0 -> 815 bytes .../client/resources/metadata.png | Bin 0 -> 603 bytes .../newres/WorkspaceExplorerAppResources.java | 52 ++ .../newres/WorkspaceExplorerIcons.java | 41 ++ .../client/resources/newres/baseIcons.css | 32 + .../client/resources/newres/cancel.png | Bin 0 -> 908 bytes .../client/resources/newres/folder.png | Bin 0 -> 380 bytes .../client/resources/newres/home.png | Bin 0 -> 403 bytes .../client/resources/newres/info-icon.png | Bin 0 -> 245 bytes .../client/resources/newres/info.png | Bin 0 -> 260 bytes .../client/resources/newres/loading.gif | Bin 0 -> 8114 bytes .../client/resources/newres/new_folder.png | Bin 0 -> 581 bytes .../client/resources/newres/vre_folder.png | Bin 0 -> 1396 bytes .../client/resources/noimage.png | Bin 0 -> 128 bytes .../client/resources/pdf_document.png | Bin 0 -> 591 bytes .../client/resources/query.png | Bin 0 -> 775 bytes .../client/resources/refresh.png | Bin 0 -> 835 bytes .../client/resources/report.png | Bin 0 -> 649 bytes .../client/resources/report_template.png | Bin 0 -> 519 bytes .../client/resources/root.png | Bin 0 -> 806 bytes .../client/resources/shared_folder.png | Bin 0 -> 887 bytes .../client/resources/timeseries.png | Bin 0 -> 566 bytes .../client/resources/url_document.png | Bin 0 -> 614 bytes .../client/resources/workflow_report.png | Bin 0 -> 756 bytes .../client/resources/workflow_template.png | Bin 0 -> 444 bytes .../rpc/WorkspaceExplorerAppService.java | 150 ++++ .../rpc/WorkspaceExplorerAppServiceAsync.java | 169 +++++ .../client/view/Breadcrumbs.java | 171 +++++ .../client/view/Breadcrumbs.ui.xml | 6 + .../client/view/PopupContextMenu.java | 63 ++ .../client/view/SelectableTypes.java | 34 + .../client/view/SelectionItem.java | 26 + .../client/view/ShowableTypes.java | 33 + .../client/view/WorkspaceExplorer.java | 361 ++++++++++ .../resources/BootstrapOverrideResources.java | 17 + .../CustomBootstrapConfigurator.java | 30 + .../resources/css/bootstrap.min.css | 74 ++ .../resources/css/gwt-bootstrap.css | 80 +++ .../DownloadWorkspaceExplorerServlet.java | 679 ++++++++++++++++++ .../server/ItemBuilder.java | 400 +++++++++++ .../server/ItemComparator.java | 46 ++ .../server/StringUtil.java | 31 + .../WorkspaceExplorerAppServiceImpl.java | 644 +++++++++++++++++ .../workspaceexplorerapp/server/WsUtil.java | 89 +++ .../shared/FilterCriteria.java | 116 +++ .../shared/HandlerResultMessage.java | 153 ++++ .../workspaceexplorerapp/shared/Item.java | 368 ++++++++++ .../shared/ItemCategory.java | 17 + .../shared/ItemInterface.java | 28 + .../workspaceexplorerapp/shared/ItemType.java | 31 + .../shared/PublicLink.java | 94 +++ .../shared/SizeFormatter.java | 49 ++ .../WorkspaceNavigatorServiceException.java | 35 + .../WorkspaceExplorerApp.gwt.xml | 28 + src/main/webapp/WEB-INF/web.xml | 31 + src/main/webapp/WorkspaceExplorerApp.css | 209 ++++++ src/main/webapp/WorkspaceExplorerApp.html | 46 ++ .../webapp/WorkspaceExplorerAppMaterial.html | 25 + src/main/webapp/error404.html | 26 + .../webapp/img/d4science_workspace_logo.png | Bin 0 -> 105770 bytes .../img/d4science_workspace_logo_180.png | Bin 0 -> 35508 bytes src/main/webapp/img/dark-noise.png | Bin 0 -> 5091 bytes src/main/webapp/img/gCubeWorkspace3.png | Bin 0 -> 7647 bytes src/main/webapp/img/gCube_70.png | Bin 0 -> 8275 bytes src/main/webapp/img/glass_cursor.cur | Bin 0 -> 2462 bytes src/main/webapp/img/glass_cursor.png | Bin 0 -> 532 bytes 148 files changed, 8839 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 .settings/.jsdtscope create mode 100644 .settings/com.google.appengine.eclipse.core.prefs create mode 100644 .settings/com.google.gdt.eclipse.core.prefs create mode 100644 .settings/com.google.gwt.eclipse.core.prefs create mode 100644 .settings/org.eclipse.core.resources.prefs create mode 100644 .settings/org.eclipse.jdt.core.prefs create mode 100644 .settings/org.eclipse.wst.common.component create mode 100644 .settings/org.eclipse.wst.common.project.facet.core.xml create mode 100644 .settings/org.eclipse.wst.validation.prefs create mode 100644 distro/LICENSE create mode 100644 distro/README create mode 100644 distro/changelog.xml create mode 100644 distro/descriptor.xml create mode 100644 distro/profile.xml create mode 100644 pom.xml create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/ItemComparatorUtility.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/NewBrowserWindow.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/SortByContextMenu.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/Util.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerApp.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppConstants.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppController.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.ui.xml create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppPanel.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.ui.xml create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerSelectNotification.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceResourcesExplorerPanel.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/DownloadType.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/RequestBuilderWorkspaceValidateItem.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/WindowOpenParameter.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEvent.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEventHandler.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/AbstractItemsCellTable.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/DisplayField.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/ItemsTable.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MaterialIconCell.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.ui.xml create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.css create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerResources.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceLightTreeResources.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/_32/folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/_32/groups_folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/ajax-loader.gif create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/aquamaps.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/document.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/error.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_file.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_image.gif create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_pdf.gif create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_resource_link.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_url.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/gcubeItem.jpeg create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/icon-unknown.gif create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/image_document.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/invalid_name.gif create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/metadata.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerAppResources.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerIcons.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/baseIcons.css create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/cancel.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/home.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/info-icon.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/info.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/loading.gif create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/new_folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/vre_folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/noimage.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/pdf_document.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/query.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/refresh.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/report.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/report_template.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/root.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/shared_folder.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/timeseries.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/url_document.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/workflow_report.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/workflow_template.png create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/rpc/WorkspaceExplorerAppService.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/rpc/WorkspaceExplorerAppServiceAsync.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.ui.xml create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/PopupContextMenu.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectableTypes.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectionItem.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/ShowableTypes.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/WorkspaceExplorer.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/BootstrapOverrideResources.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/CustomBootstrapConfigurator.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/bootstrap.min.css create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/gwt-bootstrap.css create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/DownloadWorkspaceExplorerServlet.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemBuilder.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemComparator.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/StringUtil.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WorkspaceExplorerAppServiceImpl.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WsUtil.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/FilterCriteria.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/HandlerResultMessage.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/Item.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemCategory.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemInterface.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemType.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/PublicLink.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/SizeFormatter.java create mode 100644 src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/WorkspaceNavigatorServiceException.java create mode 100644 src/main/resources/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml create mode 100644 src/main/webapp/WEB-INF/web.xml create mode 100644 src/main/webapp/WorkspaceExplorerApp.css create mode 100644 src/main/webapp/WorkspaceExplorerApp.html create mode 100644 src/main/webapp/WorkspaceExplorerAppMaterial.html create mode 100644 src/main/webapp/error404.html create mode 100644 src/main/webapp/img/d4science_workspace_logo.png create mode 100644 src/main/webapp/img/d4science_workspace_logo_180.png create mode 100644 src/main/webapp/img/dark-noise.png create mode 100644 src/main/webapp/img/gCubeWorkspace3.png create mode 100644 src/main/webapp/img/gCube_70.png create mode 100644 src/main/webapp/img/glass_cursor.cur create mode 100644 src/main/webapp/img/glass_cursor.png diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..3f26f3c --- /dev/null +++ b/.classpath @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..b65f237 --- /dev/null +++ b/.project @@ -0,0 +1,47 @@ + + + workspace-explorer-app-TRUNK + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + com.google.gdt.eclipse.core.webAppProjectValidator + + + + + com.google.gwt.eclipse.core.gwtProjectValidator + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + com.google.gwt.eclipse.core.gwtNature + + diff --git a/.settings/.jsdtscope b/.settings/.jsdtscope new file mode 100644 index 0000000..c3e8b26 --- /dev/null +++ b/.settings/.jsdtscope @@ -0,0 +1,5 @@ + + + + + diff --git a/.settings/com.google.appengine.eclipse.core.prefs b/.settings/com.google.appengine.eclipse.core.prefs new file mode 100644 index 0000000..82c36af --- /dev/null +++ b/.settings/com.google.appengine.eclipse.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +filesCopiedToWebInfLib= diff --git a/.settings/com.google.gdt.eclipse.core.prefs b/.settings/com.google.gdt.eclipse.core.prefs new file mode 100644 index 0000000..7efa2fe --- /dev/null +++ b/.settings/com.google.gdt.eclipse.core.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +jarsExcludedFromWebInfLib= +lastWarOutDir=/home/francesco-mangiacrapa/wseclipseluna/workspace-explorer-app/target/workspace-explorer-app-0.0.1-SNAPSHOT +launchConfigExternalUrlPrefix= +warSrcDir=src/main/webapp +warSrcDirIsOutput=false diff --git a/.settings/com.google.gwt.eclipse.core.prefs b/.settings/com.google.gwt.eclipse.core.prefs new file mode 100644 index 0000000..f23a752 --- /dev/null +++ b/.settings/com.google.gwt.eclipse.core.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +entryPointModules= diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000..29abf99 --- /dev/null +++ b/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +eclipse.preferences.version=1 +encoding//src/main/java=UTF-8 +encoding//src/main/resources=UTF-8 +encoding//src/test/java=UTF-8 +encoding//src/test/resources=UTF-8 +encoding/=UTF-8 diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..443e085 --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.wst.common.component b/.settings/org.eclipse.wst.common.component new file mode 100644 index 0000000..8f2836d --- /dev/null +++ b/.settings/org.eclipse.wst.common.component @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/.settings/org.eclipse.wst.common.project.facet.core.xml b/.settings/org.eclipse.wst.common.project.facet.core.xml new file mode 100644 index 0000000..ee39ed3 --- /dev/null +++ b/.settings/org.eclipse.wst.common.project.facet.core.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.settings/org.eclipse.wst.validation.prefs b/.settings/org.eclipse.wst.validation.prefs new file mode 100644 index 0000000..04cad8c --- /dev/null +++ b/.settings/org.eclipse.wst.validation.prefs @@ -0,0 +1,2 @@ +disabled=06target +eclipse.preferences.version=1 diff --git a/distro/LICENSE b/distro/LICENSE new file mode 100644 index 0000000..2d9616a --- /dev/null +++ b/distro/LICENSE @@ -0,0 +1 @@ +${gcube.license} \ No newline at end of file diff --git a/distro/README b/distro/README new file mode 100644 index 0000000..355aa76 --- /dev/null +++ b/distro/README @@ -0,0 +1,60 @@ +The gCube System - ${name} +-------------------------------------------------- + +${description} + + +${gcube.description} + +${gcube.funding} + + +Version +-------------------------------------------------- + +${version} (${buildDate}) + +Please see the file named "changelog.xml" in this directory for the release notes. + + +Authors +-------------------------------------------------- + +* Francesco Mangiacrapa (francesco.mangiacrapa-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). + +Maintainers +----------- + +* Francesco Mangiacrapa (francesco.mangiacrapa-AT-isti.cnr.it), Istituto di Scienza e Tecnologie dell'Informazione "A. Faedo" - CNR, Pisa (Italy). + +Download information +-------------------------------------------------- + +Source code is available from SVN: + ${scm.url} + +Binaries can be downloaded from the gCube website: + ${gcube.website} + + +Installation +-------------------------------------------------- + + +Documentation +-------------------------------------------------- + +Documentation is available on-line in the gCube Wiki: + ${gcube.wikiRoot}/Workspace + +Support +-------------------------------------------------- + +Bugs and support requests can be reported in the gCube issue tracking tool: + ${gcube.issueTracking} + + +Licensing +-------------------------------------------------- + +This software is licensed under the terms you may find in the file named "LICENSE" in this directory. \ No newline at end of file diff --git a/distro/changelog.xml b/distro/changelog.xml new file mode 100644 index 0000000..b4fd1ef --- /dev/null +++ b/distro/changelog.xml @@ -0,0 +1,6 @@ + + + first release + + diff --git a/distro/descriptor.xml b/distro/descriptor.xml new file mode 100644 index 0000000..0eec2ec --- /dev/null +++ b/distro/descriptor.xml @@ -0,0 +1,32 @@ + + servicearchive + + tar.gz + + / + + + ${distroDirectory} + / + true + + README + LICENSE + changelog.xml + profile.xml + + 755 + true + + + + + target/${build.finalName}.${project.packaging} + /${artifactId} + + + + diff --git a/distro/profile.xml b/distro/profile.xml new file mode 100644 index 0000000..51c3b6b --- /dev/null +++ b/distro/profile.xml @@ -0,0 +1,25 @@ + + + + Service + + ${description} + PortletUser + ${artifactId} + ${version} + + + ${artifactId} + ${version} + + ${groupId} + ${artifactId} + ${version} + + + target/${build.finalName}.war + + + + + diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..6ab2b7a --- /dev/null +++ b/pom.xml @@ -0,0 +1,319 @@ + + 4.0.0 + + maven-parent + org.gcube.tools + 1.0.0 + + + org.gcube.portlets.user + workspace-explorer-app + 0.1.0-SNAPSHOT + war + + + gCube Workspace Explorer Application is an application to navigate the Workspace in read-only mode + + + scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId} + scm:https://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId} + http://svn.d4science.research-infrastructures.eu/gcube/trunk/portlets/user/${project.artifactId} + + + + + 2.7.0 + distro + + 1.7 + 1.7 + ${project.build.directory}/${project.build.finalName} + 1.4.1 + 2.1.1 + + + + UTF-8 + UTF-8 + + + + + + org.gcube.distribution + maven-portal-bom + LATEST + pom + import + + + gwt-user + com.google.gwt + + + com.google.gwt + gwt-servlet + + + + + + + + + + + com.google.gwt + gwt-user + ${gwtVersion} + compile + + + + + + + + + + + com.github.gwtbootstrap + gwt-bootstrap + 2.3.2.0 + compile + + + + + + com.github.gwtmaterialdesign + gwt-material + ${gwt-material.version} + + + com.github.gwtmaterialdesign + gwt-material-themes + 1.4 + + + + + + + + + + + + + + + + + org.gcube.resources.discovery + ic-client + [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + provided + + + org.gcube.core + common-scope-maps + [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + compile + + + + + + org.gcube.applicationsupportlayer + aslcore + [4.0.0-SNAPSHOT, 5.0.0-SNAPSHOT) + provided + + + + + org.gcube.common + home-library-model + [1.0.0-SNAPSHOT, 2.0.0-SNAPSHOT) + provided + + + org.gcube.common + home-library-jcr + [2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT) + provided + + + asm-debug-all + org.ow2.asm + + + + + org.gcube.common + home-library + + [2.0.0-SNAPSHOT, 3.0.0-SNAPSHOT) + provided + + + asm-all + asm + + + + + + + + + + + + + org.slf4j + slf4j-api + compile + + + + org.slf4j + slf4j-log4j12 + compile + + + + + log4j + log4j + + provided + + + + junit + junit + 4.7 + test + + + + javax.validation + validation-api + 1.0.0.GA + test + + + javax.validation + validation-api + 1.0.0.GA + sources + test + + + + + + ${webappDirectory}/WEB-INF/classes + + + + + + org.codehaus.mojo + gwt-maven-plugin + ${gwtVersion} + + + + compile + + + + + + + WorkspaceExplorerApp.html + ${webappDirectory} + + + + + + org.apache.maven.plugins + maven-war-plugin + ${maven-war-plugin.version} + + + compile + + exploded + + + + + ${webappDirectory} + + + + org.apache.maven.plugins + maven-compiler-plugin + 2.3.2 + + ${maven.compiler.source} + ${maven.compiler.target} + + + + + org.apache.maven.plugins + maven-assembly-plugin + 2.2 + + + ${distroDirectory}/descriptor.xml + + + + + servicearchive + install + + single + + + + + + org.apache.maven.plugins + maven-resources-plugin + 2.5 + + + copy-profile + install + + copy-resources + + + target + + + ${distroDirectory} + true + + profile.xml + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml new file mode 100644 index 0000000..111f347 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/ItemComparatorUtility.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/ItemComparatorUtility.java new file mode 100644 index 0000000..b746f68 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/ItemComparatorUtility.java @@ -0,0 +1,89 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.DisplayField; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + + +/** + * The Class ItemComparator. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 21, 2016 + * @param the generic type + */ +public class ItemComparatorUtility { + + /** + * Instantiates a new item comparator utility. + * + * @param field the field + * @param ascending the ascending + * @param list the list + * @return + */ + public static ArrayList sortItems(DisplayField field, boolean ascending, List list) { + + if(DisplayField.NAME.equals(field)){ + Collections.sort(list, new NameCompare()); + if(ascending) + Collections.reverse(list); + }else if(DisplayField.OWNER.equals(field)){ + + } + + return new ArrayList(list); + } + + /** + * The Class NameCompare. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 21, 2016 + */ + public static class NameCompare implements Comparator { + + /** + * {@inheritDoc} + */ + @Override + public int compare(Item item1, Item item2) { + + //if one of the item is folder and the other one not, we move up the folder + boolean isItem1Folder = item1.isFolder(); + boolean isItem2Folder = item2.isFolder(); + + boolean isSpecialFolder1 = isSpecialFolder(item1); + boolean isSpecialFolder2 = isSpecialFolder(item2); + + //XOR + if (isSpecialFolder1 ^ isSpecialFolder2) return isSpecialFolder1 ? -1 : 1; + + //XOR + if (isItem1Folder ^ isItem2Folder) return isItem1Folder ? -1 : 1; + + //otherwise we compare the names + return String.CASE_INSENSITIVE_ORDER.compare(item1.getName(), item2.getName()); + } + + /** + * Checks if is special folder. + * + * @param item the item + * @return true, if is special folder + */ + private boolean isSpecialFolder(Item item) { +// return item.getName().equals(WorkspaceExplorerConstants.VRE_FOLDERS_LABEL) && item.getParent()!=null && item.getParent().isRoot(); + return item.getName().equals(WorkspaceExplorerAppConstants.VRE_FOLDERS_LABEL) && item.isSpecialFolder(); + } + } + + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/NewBrowserWindow.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/NewBrowserWindow.java new file mode 100644 index 0000000..e74c2a4 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/NewBrowserWindow.java @@ -0,0 +1,51 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import com.google.gwt.core.client.JavaScriptObject; + + +/** + * The Class NewBrowserWindow. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 23, 2016 + */ +public final class NewBrowserWindow extends JavaScriptObject { + // All types that extend JavaScriptObject must have a protected, + // no-args constructor. + /** + * Instantiates a new new browser window. + */ + protected NewBrowserWindow() { + } + + /** + * Open. + * + * @param url the url + * @param target the target + * @param options the options + * @return the new browser window + */ + public static native NewBrowserWindow open(String url, String target, + String options) /*-{ + return $wnd.open(url, target, options); + }-*/; + + /** + * Close. + */ + public native void close() /*-{ + this.close(); + }-*/; + + /** + * Sets the url. + * + * @param url the new url + */ + public native void setUrl(String url) /*-{ + if (this.location) { + this.location = url; + } + }-*/; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/SortByContextMenu.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/SortByContextMenu.java new file mode 100644 index 0000000..956642d --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/SortByContextMenu.java @@ -0,0 +1,58 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import gwt.material.design.client.ui.MaterialColumn; +import gwt.material.design.client.ui.MaterialLink; +import gwt.material.design.client.ui.MaterialRow; + +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.client.event.OrderDataByEvent; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.client.ui.PopupPanel; + + +/** + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 21, 2016 + */ +public class SortByContextMenu extends PopupPanel{ + + /** + * @param handlerManager + * @param links + */ + public SortByContextMenu(final HandlerManager handlerManager, List links) { + setAutoHideEnabled(true); + getElement().addClassName("popup-order"); + MaterialRow mr = new MaterialRow(); + MaterialColumn mc = new MaterialColumn(); + mr.add(mc); + for (int i= 0; i lenght) { + if (left) + return "..." + value.substring(value.length() - lenght + 3); + else + return value.substring(0, lenght - 3) + "..."; + } + return value; + } + + + + /** + * Gets the image resource. + * + * @param item the item + * @return the image resource + */ + public static ImageResource getImageResource(Item item) + { + if(item==null || item.getType()==null) + return WorkspaceLightTreeResources.INSTANCE.unknownType(); + + switch (item.getType()) { +// case ROOT: return WorkspaceLightTreeResources.INSTANCE.root(); + case FOLDER: { + if (item.isSharedFolder()) return WorkspaceExplorerResources.INSTANCE.shared_folder(); + else return WorkspaceExplorerResources.INSTANCE.folder(); + } + case EXTERNAL_IMAGE: return WorkspaceLightTreeResources.INSTANCE.external_image(); + case EXTERNAL_FILE: return WorkspaceLightTreeResources.INSTANCE.external_file(); + case EXTERNAL_PDF_FILE: return WorkspaceLightTreeResources.INSTANCE.external_pdf(); + case EXTERNAL_URL: return WorkspaceLightTreeResources.INSTANCE.external_url(); + case REPORT_TEMPLATE: return WorkspaceLightTreeResources.INSTANCE.report_template(); + case REPORT: return WorkspaceLightTreeResources.INSTANCE.report(); + case QUERY: return WorkspaceLightTreeResources.INSTANCE.query(); + case DOCUMENT: return WorkspaceLightTreeResources.INSTANCE.document(); + case METADATA: return WorkspaceLightTreeResources.INSTANCE.metadata(); + case PDF_DOCUMENT: return WorkspaceLightTreeResources.INSTANCE.pdf_document(); + case IMAGE_DOCUMENT: return WorkspaceLightTreeResources.INSTANCE.image_document(); + case URL_DOCUMENT: return WorkspaceLightTreeResources.INSTANCE.url_document(); + case GCUBE_ITEM: return WorkspaceLightTreeResources.INSTANCE.gucbeItem(); + case UNKNOWN_TYPE: return WorkspaceLightTreeResources.INSTANCE.unknown(); + default: { + System.err.println("Unknown item type "+item.getType()); + return WorkspaceLightTreeResources.INSTANCE.unknownType(); + } + } + } + + /** + * Gets the formatted size. + * + * @param value the value + * @return the formatted size + */ + public static String getFormattedSize(long value){ + + if(value>0){ + double kb = value/1024; + if(kb<1) + kb=1; +// return numberFormatterKB.format(kb); + return kb+"KB"; + }else if(value==0){ + return "EMPTY"; + }else + return ""; + } + + /** + * Adjust size. + * + * @param el the el + * @param panel the panel + * @param offset the offset + */ + public static void adjustSize(Element el, SimplePanel panel, int offset){ + if(el!=null){ + int heigth = el.getClientHeight(); + GWT.log("getClientHeight adjustSize el: "+heigth); + heigth = heigth-offset>100?heigth-offset:0; + if(heigth>0){ + GWT.log("set new Explorer size: "+heigth); + panel.setHeight(heigth+"px"); + } + } + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerApp.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerApp.java new file mode 100644 index 0000000..7c673d6 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerApp.java @@ -0,0 +1,98 @@ +/** + * + */ + +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import com.google.gwt.core.client.EntryPoint; +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.logical.shared.ResizeEvent; +import com.google.gwt.event.logical.shared.ResizeHandler; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.RootPanel; + +/** + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Feb 19, 2016 + */ +public class WorkspaceExplorerApp implements EntryPoint { + + + private WorkspaceExplorerAppController appController; + + /** + * This is the entry point method. + */ + public void onModuleLoad() { + + + boolean jQueryLoaded = isjQueryLoaded(); +// GWT.log("Injected : "+Resources.RESOURCES.jquery().getText()); + GWT.log("jQueryLoaded: "+jQueryLoaded); + + /*if (!jQueryLoaded) { + ScriptInjector.fromString(Resources.RESOURCES.jquery().getText()) + .setWindow(ScriptInjector.TOP_WINDOW) + .inject(); + }*/ + + /*ScriptInjector.fromString(Resources.RESOURCES.jquery().getText()) + .setWindow(ScriptInjector.TOP_WINDOW) + .inject();*/ + + appController = new WorkspaceExplorerAppController(); + appController.go(RootPanel.get(WorkspaceExplorerAppConstants.APPLICATION_DIV)); + Window.addResizeHandler(new ResizeHandler() { + + @Override + public void onResize(ResizeEvent event) { + updateSize(); + } + }); + + WorkspaceExplorerAppMainPanel mainPanel = new WorkspaceExplorerAppMainPanel(appController.getMainPanel(), appController.getEventBus(), appController.getDisplayFields()); + RootPanel.get(WorkspaceExplorerAppConstants.APPLICATION_DIV).add(mainPanel); + +// WorkspaceExplorerFoooterPanel footerPanel = new WorkspaceExplorerFoooterPanel(); +// RootPanel.get("footer_we").add(footerPanel); + + updateSize(); + } + + /** + * Checks if is j query loaded. + * + * @return true, if is j query loaded + */ + private native boolean isjQueryLoaded() /*-{ + return (typeof $wnd['jQuery'] !== 'undefined'); + }-*/; + + /** + * Update window size + */ + public static void updateSize() { + + int headerH = DOM.getElementById("we_nav_bar").getClientHeight(); + GWT.log("headerH " + headerH); + int footerH = DOM.getElementById("footer_we").getClientHeight(); + GWT.log("footerH " + footerH); + int breadcrumbsH = DOM.getElementById("breadcrumbs_we").getClientHeight(); + GWT.log("breadcrumbs_we " + breadcrumbsH); + int windowHeight = Window.getClientHeight(); + GWT.log("rootHeight " + windowHeight); + int diff = windowHeight - (headerH+footerH+breadcrumbsH)-10; + int containerH = diff>0?diff:50; + DOM.getElementById(WorkspaceExplorerAppConstants.APPLICATION_DIV).getElementsByTagName("main").getItem(0).getStyle().setHeight(containerH, Unit.PX); +// DOM.getElementById(WorkspaceExplorerAppConstants.APPLICATION_DIV).getStyle().setHeight(containerH, Unit.PX); + GWT.log("containerH " + containerH); + + Element table = DOM.getElementById("data_grid_explorer"); + if(table!=null){ + int headerTableH = 0; + table.getStyle().setHeight(containerH-headerTableH, Unit.PX); + } + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppConstants.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppConstants.java new file mode 100644 index 0000000..a671391 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppConstants.java @@ -0,0 +1,41 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import org.gcube.portlets.user.workspaceexplorerapp.client.rpc.WorkspaceExplorerAppService; +import org.gcube.portlets.user.workspaceexplorerapp.client.rpc.WorkspaceExplorerAppServiceAsync; + +import com.google.gwt.core.client.GWT; + + + +/** + * The Class WorkspaceExplorerAppConstants. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 23, 2016 + */ +public class WorkspaceExplorerAppConstants { + public static final String SPECIAL_FOLDERS_NAME = "MySpecialFolders"; + + public static final String VRE_FOLDERS_LABEL = "My VRE Folders"; + + public static final String WORKSPACE_EXPLORER_CAPTION = "Workspace Explorer"; + + public static final String WORKSPACE_EXPLORER_SAVE_AS_CAPTION = "Workspace Explorer Save As..."; + + public static final String HOME_LABEL = "Home"; + + public static final String WORKSPACE_MY_SPECIAL_FOLDERS_PATH = "/Workspace/MySpecialFolders"; + + // DIALOGS + public static final String SAVE = "Save"; + public static final String AUTO = "auto"; + public static final String SELECT = "Select"; + public static final WorkspaceExplorerAppServiceAsync workspaceNavigatorService = GWT.create(WorkspaceExplorerAppService.class); + + public static final String APPLICATION_DIV = "workspaceEplorerApplicationDiv"; + public static final String VALIDATEITEM = "validateitem"; + public static final String IDS = "ids"; + public static final String IDS_SEPARATOR = ";"; + public static final String DOWNLOAD_WORKSPACE_SERVICE = GWT.getModuleBaseURL() + "DownloadServlet"; + public static final String REDIRECTONERROR = "redirectonerror"; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppController.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppController.java new file mode 100644 index 0000000..93e7e3a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppController.java @@ -0,0 +1,140 @@ +/** + * + */ + +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerSelectNotification.WorskpaceExplorerSelectNotificationListener; +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.DisplayField; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.RootPanel; + +/** + * The Class WorkspaceExplorerAppController. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * @Oct 8, 2014 + */ +public class WorkspaceExplorerAppController { + +// private VerticalPanel mainPanel = new VerticalPanel(); + + private WorkspaceExplorerAppPanel mainPanel; + private WorkspaceResourcesExplorerPanel wsResourcesExplorerPanel; + private final HandlerManager eventBus = new HandlerManager(null); + + /** + * Instantiates a new workspace explorer app controller. + */ + public WorkspaceExplorerAppController() { + } + + /** + * Go. + * + * @param rootPanel the root panel + */ + public void go(final RootPanel rootPanel) { + RootPanel.getBodyElement().getStyle().setPadding(0, Unit.PX); +// mainPanel.setWidth("100%"); + + try { + String folderId = Window.Location.getParameter("folderId"); + + //TODO CHECK FOLDER ID + if(folderId==null) + Window.alert("Folder Id not found, it is not possible to retrieve a folder without a valid id"); + + RootPanel.get().addDomHandler(new ContextMenuHandler() { + + @Override + public void onContextMenu(ContextMenuEvent event) { + event.preventDefault(); + event.stopPropagation(); + } + }, ContextMenuEvent.getType()); + + wsResourcesExplorerPanel = new WorkspaceResourcesExplorerPanel(eventBus, folderId, false); + WorskpaceExplorerSelectNotificationListener listener = new WorskpaceExplorerSelectNotificationListener() { + + @Override + public void onSelectedItem(Item item) { + + GWT.log("Listener Selected Item " + item); + } + + @Override + public void onFailed(Throwable throwable) { + + GWT.log("There are networks problem, please check your connection."); + } + + @Override + public void onAborted() { + + } + + @Override + public void onNotValidSelection() { + + } + }; + wsResourcesExplorerPanel.addWorkspaceExplorerSelectNotificationListener(listener); + + /*new com.google.gwt.user.client.Timer() { + + @Override + public void run() { + + //TODO //IS A TEST REMOVE + ArrayList tests = new ArrayList(); + for (int i = 0; i < 50; i++) { + tests.add(new Item(i+""+Random.nextInt(), "name"+i, false)); + } + wsResourcesExplorerPanel.getWsExplorer().updateExplorer(tests); + } + }.schedule(1000);*/ + + mainPanel = new WorkspaceExplorerAppPanel(wsResourcesExplorerPanel); + } + catch (Exception e) { + e.printStackTrace(); + } + } + + + /** + * Gets the main panel. + * + * @return the mainPanel + */ + public WorkspaceExplorerAppPanel getMainPanel() { + return mainPanel; + } + + + /** + * Gets the event bus. + * + * @return the event bus + */ + public HandlerManager getEventBus(){ + return eventBus; + } + + /** + * Gets the display fields. + * + * @return the display fields + */ + public DisplayField[] getDisplayFields(){ + return wsResourcesExplorerPanel.getDisplayFields(); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.java new file mode 100644 index 0000000..bfd02d7 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.java @@ -0,0 +1,157 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import gwt.material.design.client.constants.IconPosition; +import gwt.material.design.client.constants.IconType; +import gwt.material.design.client.ui.MaterialLink; +import gwt.material.design.client.ui.MaterialNavBar; +import gwt.material.design.client.ui.MaterialNavSection; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.client.download.DownloadType; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.DownloadItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.DisplayField; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.HTMLPanel; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Widget; + + +/** + * The Class WorkspaceExplorerAppMainPanel. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 2, 2016 + */ +public class WorkspaceExplorerAppMainPanel extends Composite { + + private static WorkspaceExplorerAppMainPanelUiBinder uiBinder = + GWT.create(WorkspaceExplorerAppMainPanelUiBinder.class); + + /** + * The Interface WorkspaceExplorerAppMainPanelUiBinder. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 8, 2016 + */ + interface WorkspaceExplorerAppMainPanelUiBinder + extends UiBinder { + } + + @UiField + HTMLPanel explorer_main_container; + + @UiField + HTMLPanel we_html_base_panel; + + @UiField + MaterialNavBar we_nav_bar; + + @UiField + MaterialNavSection we_nav_right; + + @UiField + MaterialLink download_we; + + @UiField + MaterialLink show_we; + + @UiField + Image d4science_workspace_logo_180; + + private HandlerManager handlerManager; + + /** + * Because this class has a default constructor, it can + * be used as a binder template. In other words, it can be used in other + * *.ui.xml files as follows: + * + * Hello! + * + * Note that depending on the widget that is used, it may be necessary to + * implement HasHTML instead of HasText. + * + * @param workspaceExplorerAppPanel the workspace explorer app panel + * @param handlerManager the handler manager + */ + public WorkspaceExplorerAppMainPanel(WorkspaceExplorerAppPanel workspaceExplorerAppPanel, HandlerManager handlerManager, DisplayField[] displayFields) { + initWidget(uiBinder.createAndBindUi(this)); + this.handlerManager = handlerManager; + explorer_main_container.add(workspaceExplorerAppPanel); + we_nav_bar.getElement().setId("we_nav_bar"); + we_nav_bar.getElement().setAttribute("id", "we_nav_bar"); + + final MaterialLink order = new MaterialLink("Order by"); + order.setTitle("Order data for item selected"); + order.setActivates("order_list"); + order.setTextColor("white"); + order.setIconType(IconType.ARROW_DROP_DOWN); + order.setIconPosition(IconPosition.RIGHT); + + final List links = new ArrayList(displayFields.length); + for (final DisplayField field : displayFields) { + if(field.isSortable()){ + MaterialLink link = new MaterialLink(field.getLabel()); + link.addStyleName("under-line-onhover"); + links.add(link); + } + } + + final SortByContextMenu scm = new SortByContextMenu(this.handlerManager, links); + + order.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + GWT.log("clicked : "+event.getSource().toString()); + scm.showRelativeTo(order); + } + }); + + we_nav_right.add(order); + download_we.addClickHandler(new ClickHandler() { + + /* (non-Javadoc) + * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) + */ + @Override + public void onClick(ClickEvent event) { + WorkspaceExplorerAppMainPanel.this.handlerManager.fireEvent(new DownloadItemEvent(null, DownloadType.DOWNLOAD)); + } + }); + + show_we.addClickHandler(new ClickHandler() { + + /* (non-Javadoc) + * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) + */ + @Override + public void onClick(ClickEvent event) { + WorkspaceExplorerAppMainPanel.this.handlerManager.fireEvent(new DownloadItemEvent(null, DownloadType.OPEN)); + } + }); + + d4science_workspace_logo_180.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + Window.open("https://www.d4science.org", "_blank", null); + } + }); + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.ui.xml b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.ui.xml new file mode 100644 index 0000000..8fee8c6 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppMainPanel.ui.xml @@ -0,0 +1,75 @@ + + + + .adminMainContent { + overflow: auto; + } + + /*.label { + margin-left: 210px; + font-family: sans-serif; + font-size: 16px; + text-align: left; + font-weight: bold; + }*/ + + .nav-right { + /*padding-left: 200px;*/ +/* font-size: 16px;*/ + /*text-align: right;*/ + /*width: 200px;*/ + } + + + .title-left { + /*font-family: sans-serif;*/ + font-size: 14px; + text-align: left; + font-weight: bold; + } + + .navigation_explorer { + padding-bottom: 50px; + padding-left: 5px; + padding-top: 10px; + } + + .navigation_explorer :HOVER { + cursor: pointer !important; + } + + .navigation_bar { + height: 100px; + } + + header, main, footer { + padding-left: 200px; + } + + + + + Workspace Explorer + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppPanel.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppPanel.java new file mode 100644 index 0000000..5cd85cf --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerAppPanel.java @@ -0,0 +1,33 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import com.google.gwt.user.client.ui.SimplePanel; +import com.google.gwt.user.client.ui.Widget; + + +/** + * The Class SplitPanel. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 23, 2015 + */ +public class WorkspaceExplorerAppPanel extends SimplePanel{ + + + /** + * Instantiates a new workspace explorer app panel. + * + * @param splitterSize the splitter size + * @param navigation the navigation + * @param wsExplorer the ws explorer + */ + public WorkspaceExplorerAppPanel(Widget wsExplorerPanel) { + ensureDebugId("WorkspaceExplorerAppPanel"); + this.getElement().setId("WorkspaceExplorerAppPanel"); + this.getElement().setAttribute("id","WorkspaceExplorerAppPanel"); + setWidth("100%"); + add(wsExplorerPanel); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.java new file mode 100644 index 0000000..072d34d --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.java @@ -0,0 +1,51 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import gwt.material.design.client.ui.MaterialFooter; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + + +/** + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 18, 2016 + */ +public class WorkspaceExplorerFoooterPanel extends Composite { + + private static WorkspaceExplorerFoooterPanelUiBinder uiBinder = + GWT.create(WorkspaceExplorerFoooterPanelUiBinder.class); + + interface WorkspaceExplorerFoooterPanelUiBinder + extends UiBinder { + } + + /** + * Because this class has a default constructor, it can + * be used as a binder template. In other words, it can be used in other + * *.ui.xml files as follows: + * + * Hello! + * + * Note that depending on the widget that is used, it may be necessary to + * implement HasHTML instead of HasText. + */ + public WorkspaceExplorerFoooterPanel() { + + initWidget(uiBinder.createAndBindUi(this)); + } + @UiField + MaterialFooter we_footer_bar; + + public WorkspaceExplorerFoooterPanel(String firstName) { + + initWidget(uiBinder.createAndBindUi(this)); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.ui.xml b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.ui.xml new file mode 100644 index 0000000..5cc0aea --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerFoooterPanel.ui.xml @@ -0,0 +1,14 @@ + + + + .we_footer { + height: 50px important! + } + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerSelectNotification.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerSelectNotification.java new file mode 100644 index 0000000..a539db1 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceExplorerSelectNotification.java @@ -0,0 +1,94 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + + +/** + * The Class WorskpaceExplorerNotification. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 29, 2015 + */ +public class WorkspaceExplorerSelectNotification { + + + + /** + * The listener interface for receiving worskpaceExplorerSelectNotification events. + * The class that is interested in processing a worskpaceExplorerSelectNotification + * event implements this interface, and the object created + * with that class is registered with a component using the + * component's addWorskpaceExplorerSelectNotificationListener method. When + * the worskpaceExplorerSelectNotification event occurs, that object's appropriate + * method is invoked. + * + * @see WorskpaceExplorerSelectNotificationEvent + */ + public interface WorskpaceExplorerSelectNotificationListener { + + /** + * On selected item. + * + * @param item the item + */ + void onSelectedItem(Item item); + + + /** + * On aborted. + */ + void onAborted(); + + + /** + * On failed. + * + * @param throwable the throwable + */ + void onFailed(Throwable throwable); + + + /** + * On not valid selection. + */ + void onNotValidSelection(); + } + + + + /** + * The listener interface for receiving hasWorskpaceExplorerSelectNotification events. + * The class that is interested in processing a hasWorskpaceExplorerSelectNotification + * event implements this interface, and the object created + * with that class is registered with a component using the + * component's addHasWorskpaceExplorerSelectNotificationListener method. When + * the hasWorskpaceExplorerSelectNotification event occurs, that object's appropriate + * method is invoked. + * + * @see HasWorskpaceExplorerSelectNotificationEvent + */ + public interface HasWorskpaceExplorerSelectNotificationListener { + + + /** + * Adds the workspace explorer select notification listener. + * + * @param handler the handler + */ + public void addWorkspaceExplorerSelectNotificationListener(WorskpaceExplorerSelectNotificationListener handler); + + + + /** + * Removes the workspace explorer select notification listener. + * + * @param handler the handler + */ + public void removeWorkspaceExplorerSelectNotificationListener(WorskpaceExplorerSelectNotificationListener handler); + + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceResourcesExplorerPanel.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceResourcesExplorerPanel.java new file mode 100644 index 0000000..f7d97cd --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/WorkspaceResourcesExplorerPanel.java @@ -0,0 +1,510 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client; + +import gwt.material.design.client.ui.MaterialToast; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerSelectNotification.HasWorskpaceExplorerSelectNotificationListener; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerSelectNotification.WorskpaceExplorerSelectNotificationListener; +import org.gcube.portlets.user.workspaceexplorerapp.client.download.RequestBuilderWorkspaceValidateItem; +import org.gcube.portlets.user.workspaceexplorerapp.client.download.WindowOpenParameter; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.BreadcrumbClickEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.BreadcrumbClickEventHandler; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.ClickItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.ClickItemEventHandler; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.DownloadItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.DownloadItemEventHandler; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.LoadFolderEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.LoadFolderEventHandler; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.OrderDataByEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.OrderDataByEventHandler; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.RightClickItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.RightClickItemEventHandler; +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.DisplayField; +import org.gcube.portlets.user.workspaceexplorerapp.client.view.Breadcrumbs; +import org.gcube.portlets.user.workspaceexplorerapp.client.view.PopupContextMenu; +import org.gcube.portlets.user.workspaceexplorerapp.client.view.WorkspaceExplorer; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; + +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.core.shared.GWT; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.http.client.RequestBuilder; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.DockPanel; +import com.google.gwt.user.client.ui.ScrollPanel; +import com.google.gwt.user.client.ui.VerticalPanel; + + +/** + * The Class WorkspaceResourcesExplorerPanel. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Dec 3, 2015 + */ +public class WorkspaceResourcesExplorerPanel extends DockPanel implements HasWorskpaceExplorerSelectNotificationListener{ + + public HandlerManager eventBus; + private Breadcrumbs breadcrumbs; + private boolean isSelect = false; + private String captionTxt; +// private WorkspaceExplorerController controller; + private List listeners = new ArrayList(); + private VerticalPanel mainVP = new VerticalPanel(); +// private HorizontalPanel footerHP = new HorizontalPanel(); + private WorkspaceExplorer wsExplorer; + private ScrollPanel centerScrollable = new ScrollPanel(); +// private ScrollPanel southPanel = new ScrollPanel(); + private String folderId; + private String folderName; + private DisplayField[] displayFields = new DisplayField[]{DisplayField.ICON, DisplayField.NAME, DisplayField.OWNER, DisplayField.CREATION_DATE}; + + /** + * Instantiates a new workspace folder explorer select panel. + * + * @param eventBus the event bus + * @param folderId the folder id like root folder to explore + * @param folderName the folder name + * @throws Exception the exception + */ + public WorkspaceResourcesExplorerPanel(HandlerManager eventBus, String folderId, String folderName) throws Exception { + initExplorer(eventBus, folderId, folderName, ItemType.values(), ItemType.values()); + } + + /** + * Inits the explorer. + * + * @param eventBus the event bus + * @param folderId the folder id + * @param folderName the folder name + * @param selectableTypes the selectable types + * @param showableTypes the showable types + * @throws Exception the exception + */ + private void initExplorer(HandlerManager eventBus, String folderId, String folderName, ItemType[] selectableTypes, ItemType[] showableTypes) throws Exception{ + this.folderId = folderId; + this.folderName = folderName; + this.eventBus = eventBus; + this.breadcrumbs = new Breadcrumbs(eventBus); + bindEvents(); + + wsExplorer = new WorkspaceExplorer(eventBus, showableTypes, selectableTypes, displayFields); + Item item = new Item(folderId, folderName, true); + if(folderId!=null && !folderId.isEmpty()) + wsExplorer.loadFolder(item); + initPanel(""); + } + + + /** + * @return the displayFields + */ + public DisplayField[] getDisplayFields() { + + return displayFields; + } + + /** + * Instantiates a new workspace explorer select panel. + * + * @param folderId the folder id + * @param showOnlyFolders the show only folders + * @throws Exception the exception + */ + public WorkspaceResourcesExplorerPanel(HandlerManager eventBus, String folderId, boolean showOnlyFolders) throws Exception { + + if(showOnlyFolders){ + ItemType[] itemsType = new ItemType[1]; + itemsType[0] = ItemType.FOLDER; + initExplorer(eventBus, folderId, "", itemsType, itemsType); + }else{ + initExplorer(eventBus, folderId, "", ItemType.values(), ItemType.values()); + } + } + + + /** + * Bind events. + */ + private void bindEvents(){ + + eventBus.addHandler(ClickItemEvent.TYPE, new ClickItemEventHandler() { + + @Override + public void onClick(final ClickItemEvent clickItemEvent) { + isSelect = false; + Set items = wsExplorer.getItemsSelected(); + List lstItems = toList(items); + + //Return if item is not selectable + if(!itemIsSelectable(lstItems.get(0))){ + notifyNotValidSelection(); + return; + } + + notifySelectedItem(lstItems.get(0)); + isSelect = true; + } + }); + + eventBus.addHandler(LoadFolderEvent.TYPE, new LoadFolderEventHandler() { + + @Override + public void onLoadFolder(LoadFolderEvent loadFolderEvent) { + + if(loadFolderEvent.getTargetFolder()==null) + return; + + Item item = loadFolderEvent.getTargetFolder(); + if(item.isFolder()){ + try { + wsExplorer.loadFolder(item); + loadParentBreadcrumbByItemId(item.getId(), true); +// clearMoreInfo(); + } catch (Exception e) { + GWT.log(e.getMessage()); + } + } + } + }); + + eventBus.addHandler(BreadcrumbClickEvent.TYPE, new BreadcrumbClickEventHandler() { + + @Override + public void onBreadcrumbClick(BreadcrumbClickEvent breadcrumbClickEvent) { + if(breadcrumbClickEvent.getTargetItem()!=null) + eventBus.fireEvent(new LoadFolderEvent(breadcrumbClickEvent.getTargetItem())); + } + }); + + eventBus.addHandler(OrderDataByEvent.TYPE, new OrderDataByEventHandler() { + + @Override + public void onOrderDataBy(OrderDataByEvent orderDataByEvent) { + + wsExplorer.getItTables().sortDataBy(orderDataByEvent.getLabel()); + + /*ArrayList items = ItemComparatorUtility.sortItems(DisplayField.NAME, true, wsExplorer.getItTables().getDataProvider().getList()); + wsExplorer.updateExplorer(items);*/ + } + }); + + + eventBus.addHandler(RightClickItemEvent.TYPE, new RightClickItemEventHandler() { + + @Override + public void onClick(RightClickItemEvent rightClickItemEvent) { + + if(rightClickItemEvent.getItem()!=null && rightClickItemEvent.getItem().getId()!=null){ + + PopupContextMenu popupCM = new PopupContextMenu(true, eventBus, rightClickItemEvent.getItem()); + popupCM.showPopup(rightClickItemEvent.getXPos(), Window.getScrollTop()+rightClickItemEvent.getYPos()); + + /*final PopupPanel contextMenu = new PopupPanel(true); + contextMenu.getElement().getStyle().setBackgroundColor("#F5F5F5"); + Navigation nav = new Navigation(eventBus, rightClickItemEvent.getItem()); + nav.addCommandOnDownloadClick(new Command() { + + @Override + public void execute() { + contextMenu.hide(); + } + }); + contextMenu.add(nav); + contextMenu.setPopupPosition(rightClickItemEvent.getXPos(), Window.getScrollTop()+rightClickItemEvent.getYPos()); + contextMenu.show();*/ + } + } + }); + + eventBus.addHandler(DownloadItemEvent.TYPE, new DownloadItemEventHandler() { + + @Override + public void onDownloadItem(DownloadItemEvent downloadItemEvent) { + GWT.log("Fired event DownloadItemEvent"); + String itemIds = ""; + if(downloadItemEvent.getItem()!=null) + itemIds = downloadItemEvent.getItem().getId()+WorkspaceExplorerAppConstants.IDS_SEPARATOR; + else{ + + List lstItems = toList(wsExplorer.getItemsSelected()); + for (Item item : lstItems) { + itemIds +=item.getId()+WorkspaceExplorerAppConstants.IDS_SEPARATOR; + } + } + GWT.log("itemIds: "+itemIds); + if(!itemIds.isEmpty()){ +// MaterialToast.fireToast("Download..."); + + switch (downloadItemEvent.getType()) { + case DOWNLOAD: + MaterialToast.fireToast("Download..."); + try { + new RequestBuilderWorkspaceValidateItem(RequestBuilder.GET,WorkspaceExplorerAppConstants.DOWNLOAD_WORKSPACE_SERVICE, WorkspaceExplorerAppConstants.IDS+"="+itemIds, "_self", downloadHandlerCallback); + } catch (Exception e) { + Window.alert("Sorry, an error occurred while contacting server, try again"); + } + break; + case PREVIEW: + break; + case OPEN: + MaterialToast.fireToast("Showing..."); + try { + new RequestBuilderWorkspaceValidateItem(RequestBuilder.GET, WorkspaceExplorerAppConstants.DOWNLOAD_WORKSPACE_SERVICE, WorkspaceExplorerAppConstants.IDS+"="+itemIds+"&viewContent=true", "_blank", downloadHandlerCallback); + + } catch (Exception e) { + Window.alert("Sorry, an error occurred while contacting server, try again"); + } + break; + default: + break; + } + + + /*final NewBrowserWindow newBW = NewBrowserWindow.open("", "_self", ""); + WorkspaceExplorerAppConstants.workspaceNavigatorService.getPublicLinkForItemId(itemId, new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Window.alert(caught.getMessage()); + } + + @Override + public void onSuccess(String url) { + + if(url!=null){ + newBW.setUrl(url); + }else + Window.alert("Sorry, the item selected is not available for download"); + + } + });*/ + } + } + }); + } + + + /** + * To list. + * + * @param items the items + * @return the list + */ + private List toList(Set items){ + if(items!=null && items.size()>0){ + List lstItems = new ArrayList (items.size()); + lstItems.addAll(items); + return lstItems; + } + return null; + } + + + /** + * Load parent breadcrumb by item id. + * + * @param itemIdentifier the item identifier + * @param includeItemAsParent the include item as parent + */ + private void loadParentBreadcrumbByItemId(final String itemIdentifier, boolean includeItemAsParent){ + + GWT.log("Reload Parent Breadcrumb: [Item id: "+itemIdentifier+"]"); + + WorkspaceExplorerAppConstants.workspaceNavigatorService.getBreadcrumbsByItemIdentifierToParentLimit(itemIdentifier, folderId, includeItemAsParent, new AsyncCallback>() { + + @Override + public void onFailure(Throwable caught) { + GWT.log(caught.getMessage()); + wsExplorer.setAlert(caught.getMessage(), AlertType.ERROR); + } + + @Override + public void onSuccess(List result) { + if(result!=null){ + breadcrumbs.setPath(result); +// clearMoreInfo(); + } + } + }); + } + + + /** + * Refresh root folder view. + */ + public void refreshRootFolderView(){ + Item item = new Item(folderId, folderName, true); + eventBus.fireEvent(new LoadFolderEvent(item)); + } + +// /** +// * Clear more info. +// */ +// private void clearMoreInfo(){ +// southPanel.clear(); +// } + + /** + * Inits the panel. + * + * @param captionTxt the caption txt is the tool-tip + */ + private void initPanel(String captionTxt) { + this.captionTxt = captionTxt; + this.getElement().setId("WorkspaceExplorerContainer"); + this.getElement().setAttribute("id", "WorkspaceExplorerContainer"); + this.getElement().addClassName("workspace-explorer-container"); + + if(this.captionTxt!=null && !this.captionTxt.isEmpty()) + setTitle(this.captionTxt); + + setWidth("100%"); + add(breadcrumbs, DockPanel.NORTH); + mainVP.add(wsExplorer.getPanel()); + centerScrollable.add(mainVP); + add(centerScrollable, DockPanel.CENTER); + } + + /** + * Notify selected item. + * + * @param selected the selected + */ + private void notifySelectedItem(Item selected){ + + for (WorskpaceExplorerSelectNotificationListener worskpaceExplorerNotificationListener : listeners) { + worskpaceExplorerNotificationListener.onSelectedItem(selected); + } + } + + /** + * Notify aborted. + */ + private void notifyAborted(){ + + for (WorskpaceExplorerSelectNotificationListener worskpaceExplorerNotificationListener : listeners) { + worskpaceExplorerNotificationListener.onAborted(); + } + } + + + /** + * Notify not valid selection. + */ + private void notifyNotValidSelection(){ + + for (WorskpaceExplorerSelectNotificationListener worskpaceExplorerNotificationListener : listeners) { + worskpaceExplorerNotificationListener.onNotValidSelection(); + } + } + + /** + * Notify failed. + * + * @param t the t + */ + @SuppressWarnings("unused") + private void notifyFailed(Throwable t){ + + for (WorskpaceExplorerSelectNotificationListener worskpaceExplorerNotificationListener : listeners) { + worskpaceExplorerNotificationListener.onFailed(t); + } + } + + /** + * Gets the caption txt. + * + * @return the captionTxt + */ + public String getCaptionTxt() { + return captionTxt; + } + + /** + * Checks if is valid hide. + * + * @return the isValidHide + */ + public boolean isValidHide() { + return isSelect; + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.notification.WorskpaceExplorerNotification.HasWorskpaceExplorerNotificationListener#addWorkspaceExplorerNotificationListener(org.gcube.portlets.widgets.wsexplorer.client.notification.WorskpaceExplorerNotification.WorskpaceExplorerNotificationListener) + */ + @Override + public void addWorkspaceExplorerSelectNotificationListener(WorskpaceExplorerSelectNotificationListener handler) { + if(handler!=null) + listeners.add(handler); + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.notification.WorskpaceExplorerNotification.HasWorskpaceExplorerNotificationListener#removeWorkspaceExplorerNotificationListener(org.gcube.portlets.widgets.wsexplorer.client.notification.WorskpaceExplorerNotification.WorskpaceExplorerNotificationListener) + */ + @Override + public void removeWorkspaceExplorerSelectNotificationListener(WorskpaceExplorerSelectNotificationListener handler) { + if(handler!=null){ + if(listeners.contains(handler)) + listeners.remove(handler); + } + } + + /** + * Item is selectable. + * + * @param item the item + * @return true, if successful + */ + public boolean itemIsSelectable(Item item){ + GWT.log("Selectable type: "+wsExplorer.getSelectableTypes()); + GWT.log("item: "+item); + if (item!=null){ + boolean selectable = wsExplorer.getSelectableTypes().contains(item.getType()); + return selectable?true:false; + } + return false; + } + + + /** + * @return the wsExplorer + */ + public WorkspaceExplorer getWsExplorer() { + return wsExplorer; + } + + /** + * Gets the event bus. + * + * @return the eventBus + */ + public HandlerManager getEventBus() { + + return eventBus; + } + + public AsyncCallback downloadHandlerCallback = new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + + } + + @Override + public void onSuccess(WindowOpenParameter windowOpenParam) { + String params = "?"+windowOpenParam.getParameters(); + if(params.length()>1) + params+="&"; + params+=WorkspaceExplorerAppConstants.REDIRECTONERROR+"="+windowOpenParam.isRedirectOnError(); + windowOpenParam.getBrowserWindow().setUrl(WorkspaceExplorerAppConstants.DOWNLOAD_WORKSPACE_SERVICE+params); + } + }; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/DownloadType.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/DownloadType.java new file mode 100644 index 0000000..189203d --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/DownloadType.java @@ -0,0 +1,18 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.download; + + +/** + * The Enum DownloadType. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 7, 2016 + */ +public enum DownloadType { + + PREVIEW, + OPEN, + DOWNLOAD; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/RequestBuilderWorkspaceValidateItem.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/RequestBuilderWorkspaceValidateItem.java new file mode 100644 index 0000000..3a70979 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/RequestBuilderWorkspaceValidateItem.java @@ -0,0 +1,121 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.download; + +import org.gcube.portlets.user.workspaceexplorerapp.client.NewBrowserWindow; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerAppConstants; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.http.client.Request; +import com.google.gwt.http.client.RequestBuilder; +import com.google.gwt.http.client.RequestCallback; +import com.google.gwt.http.client.RequestException; +import com.google.gwt.http.client.Response; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; + +/** + * The Class RequestBuilderWorkspaceValidateItem. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * @Jun 24, 2013 + */ +public class RequestBuilderWorkspaceValidateItem { + + private AsyncCallback callback; + private String parameters; + + /** + * Instantiates a new request builder workspace validate item. + * + * @param method the method + * @param servletName the name of the servlet that must be called + * @param params param=value¶m1=value1&... + * @param targetWindow the target of the window (e.g. "_blank") + * @param callback the callback + * @throws Exception the exception + */ + public RequestBuilderWorkspaceValidateItem(RequestBuilder.Method method, String servletName, final String params, final String targetWindow, final AsyncCallback callback) throws Exception{ + + this.callback = callback; + + final NewBrowserWindow newBrowserWindow = NewBrowserWindow.open("", targetWindow, ""); + + this.parameters = params; + + if(servletName==null) + return; + + servletName = servletName.isEmpty()?"/":servletName; + + if(!servletName.contains("/")) + servletName+="/"+servletName; + + if(parameters==null) + parameters = WorkspaceExplorerAppConstants.VALIDATEITEM+"=true"; + else + parameters +="&"+WorkspaceExplorerAppConstants.VALIDATEITEM+"=true"; + + String urlRequest = servletName+"?"+parameters; + + GWT.log("request builder for: "+urlRequest); + + RequestBuilder requestBuilder = new RequestBuilder(method, urlRequest); + try { + + requestBuilder.sendRequest("", new RequestCallback() { + + @Override + public void onResponseReceived(Request request, Response response) { + + int status = response.getStatusCode(); + + if(!(status==200) && !(status==202)){ //NOT IS STATUS SC_ACCEPTED + +// if(status==401){ // SC_UNAUTHORIZED = 401; +// GWT.log("Session expired"); +// AppControllerExplorer.getEventBus().fireEvent(new SessionExpiredEvent()); +// return; +// } + newBrowserWindow.close(); + handleError("Sorry, an error occurred on retriving the file. "+response.getText()); //ERROR STATUS + + }else { //OK STATUS + + if(callback!=null){ + //PASSING PARAMS WITHOUT VALIDATION=TRUE + callback.onSuccess(new WindowOpenParameter(targetWindow, "", params, true, newBrowserWindow)); + } + } + } + + @Override + public void onError(Request request, Throwable exception) { + newBrowserWindow.close(); + +// System.out.println("exception message is "+exception.getMessage()); + handleError(exception.getMessage()); + } + }); + + } catch (RequestException e) { + newBrowserWindow.close(); + throw new Exception("Sorry, an error occurred while contacting server, try again"); + } + } + + /** + * Handle error. + * + * @param message the message + */ + public void handleError(String message){ + + if(callback!=null) + callback.onFailure(new Exception(message)); + else + Window.alert("Error: "+message); + + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/WindowOpenParameter.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/WindowOpenParameter.java new file mode 100644 index 0000000..754380a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/download/WindowOpenParameter.java @@ -0,0 +1,91 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.download; + +import org.gcube.portlets.user.workspaceexplorerapp.client.NewBrowserWindow; + +/** + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * @Jun 25, 2013 + * + */ +public class WindowOpenParameter { + + private String option; + private String parameters; + private String itemName; + private boolean redirectOnError; + private NewBrowserWindow browserWindow; + + /** + * + */ + public WindowOpenParameter() { + } + + + /** + * + * @param target the target of the window (e.g. "_blank") + * @param itemName + * @param parameters param=value¶m1=value1&... + * @param redirectOnError if true execute a redirect on fake URL + * @param browserWindow an instance of NewBrowserWindow + */ + public WindowOpenParameter(String target, String itemName, String parameters, boolean redirectOnError, NewBrowserWindow browserWindow) { + super(); + this.option = target; + this.itemName = itemName; + this.parameters = parameters; + this.redirectOnError = redirectOnError; + this.browserWindow = browserWindow; + } + + + public String getParameters() { + return parameters; + } + + public void setParameters(String parameters) { + this.parameters = parameters; + } + + public String getOption() { + return option; + } + + public void setOption(String option) { + this.option = option; + } + + + public String getItemName() { + return itemName; + } + + + public void setItemName(String itemName) { + this.itemName = itemName; + } + + + public boolean isRedirectOnError() { + return redirectOnError; + } + + + public void setRedirectOnError(boolean redirectOnError) { + this.redirectOnError = redirectOnError; + } + + + public NewBrowserWindow getBrowserWindow() { + return browserWindow; + } + + + public void setBrowserWindow(NewBrowserWindow browserWindow) { + this.browserWindow = browserWindow; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEvent.java new file mode 100644 index 0000000..b7ab6b6 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEvent.java @@ -0,0 +1,61 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.event.shared.GwtEvent; + + +/** + * The Class BreadcrumbClickEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Aug 3, 2015 + */ +public class BreadcrumbClickEvent extends GwtEvent { + public static Type TYPE = new Type(); + private Item targetItem; + + + /** + * Instantiates a new breadcrumb click event. + * + * @param target the target + */ + public BreadcrumbClickEvent(Item target) { + this.targetItem = target; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(BreadcrumbClickEventHandler handler) { + handler.onBreadcrumbClick(this); + } + + /** + * Gets the target item. + * + * @return the targetItem + */ + public Item getTargetItem() { + return targetItem; + } + + /** + * Sets the target item. + * + * @param targetItem the targetItem to set + */ + public void setTargetItem(Item targetItem) { + this.targetItem = targetItem; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEventHandler.java new file mode 100644 index 0000000..5b4f541 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbClickEventHandler.java @@ -0,0 +1,20 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface BreadcrumbClickEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Aug 3, 2015 + */ +public interface BreadcrumbClickEventHandler extends EventHandler { + + /** + * On breadcrumb click. + * + * @param breadcrumbClickEvent the breadcrumb click event + */ + void onBreadcrumbClick(BreadcrumbClickEvent breadcrumbClickEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEvent.java new file mode 100644 index 0000000..5b54f90 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEvent.java @@ -0,0 +1,61 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.event.shared.GwtEvent; + + +/** + * The Class BreadcrumbInitEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 2, 2016 + */ +public class BreadcrumbInitEvent extends GwtEvent { + public static Type TYPE = new Type(); + private Item targetItem; + + + /** + * Instantiates a new breadcrumb click event. + * + * @param target the target + */ + public BreadcrumbInitEvent(Item target) { + this.targetItem = target; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(BreadcrumbInitEventHandler handler) { + handler.onBreadcrumbInit(this); + } + + /** + * Gets the target item. + * + * @return the targetItem + */ + public Item getTargetItem() { + return targetItem; + } + + /** + * Sets the target item. + * + * @param targetItem the targetItem to set + */ + public void setTargetItem(Item targetItem) { + this.targetItem = targetItem; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEventHandler.java new file mode 100644 index 0000000..0c3edf9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/BreadcrumbInitEventHandler.java @@ -0,0 +1,20 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface BreadcrumbInitEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 2, 2016 + */ +public interface BreadcrumbInitEventHandler extends EventHandler { + + /** + * On breadcrumb init. + * + * @param breadcrumbInitEvent the breadcrumb init event + */ + void onBreadcrumbInit(BreadcrumbInitEvent breadcrumbInitEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEvent.java new file mode 100644 index 0000000..5c0cc4a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEvent.java @@ -0,0 +1,54 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import java.util.Set; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.event.shared.GwtEvent; + + +/** + * The Class ClickItemEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 6, 2015 + */ +public class ClickItemEvent extends GwtEvent { + public static Type TYPE = new Type(); + private Set items; + + + /** + * Instantiates a new click item event. + * + * @param selectedObject the item + */ + public ClickItemEvent(Set selectedObject) { + this.items = selectedObject; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(ClickItemEventHandler handler) { + handler.onClick(this); + } + + /** + * Gets the items. + * + * @return the items + */ + public Set getItems() { + return items; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEventHandler.java new file mode 100644 index 0000000..46c5455 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/ClickItemEventHandler.java @@ -0,0 +1,20 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface ClickItemEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 6, 2015 + */ +public interface ClickItemEventHandler extends EventHandler { + + /** + * On click. + * + * @param moreInfoShowEvent the more info show event + */ + void onClick(ClickItemEvent moreInfoShowEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEvent.java new file mode 100644 index 0000000..1fe5e90 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEvent.java @@ -0,0 +1,36 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.GwtEvent; + + +/** + * The Class CreateFolderClickEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 1, 2016 + */ +public class CreateFolderClickEvent extends GwtEvent { + public static Type TYPE = new Type(); + + /** + * Instantiates a new click item event. + */ + public CreateFolderClickEvent() { + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(CreateFolderClickEventHandler handler) { + handler.onClick(this); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEventHandler.java new file mode 100644 index 0000000..d7eeb4c --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/CreateFolderClickEventHandler.java @@ -0,0 +1,20 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface ClickItemEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 6, 2015 + */ +public interface CreateFolderClickEventHandler extends EventHandler { + + /** + * On click. + * + * @param createFolderClickEvent the more info show event + */ + void onClick(CreateFolderClickEvent createFolderClickEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEvent.java new file mode 100644 index 0000000..9a63a03 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEvent.java @@ -0,0 +1,63 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import org.gcube.portlets.user.workspaceexplorerapp.client.download.DownloadType; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemInterface; + +import com.google.gwt.event.shared.GwtEvent; + + +/** + * The Class ClickItemEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 6, 2015 + */ +public class DownloadItemEvent extends GwtEvent { + public static Type TYPE = new Type(); + private ItemInterface item; + private DownloadType type; + + /** + * Instantiates a new click item event. + * + * @param itemDownload the item download + * @param type the type + */ + public DownloadItemEvent(ItemInterface itemDownload, DownloadType type) { + this.item = itemDownload; + this.type = type; + } + + /** + * @return the type + */ + public DownloadType getType() { + + return type; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(DownloadItemEventHandler handler) { + handler.onDownloadItem(this); + } + + /** + * Gets the item. + * + * @return the item + */ + public ItemInterface getItem() { + return item; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEventHandler.java new file mode 100644 index 0000000..d29a3db --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/DownloadItemEventHandler.java @@ -0,0 +1,19 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + +/** + * The Interface DownloadItemEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 23, 2016 + */ +public interface DownloadItemEventHandler extends EventHandler { + + /** + * On download item. + * + * @param downloadItemEvent the download item event + */ + void onDownloadItem(DownloadItemEvent downloadItemEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEvent.java new file mode 100644 index 0000000..361c05f --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEvent.java @@ -0,0 +1,61 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.event.shared.GwtEvent; + + + +/** + * The Class LoadFolderEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +public class LoadFolderEvent extends GwtEvent { + public static Type TYPE = new Type(); + private Item item; + + /** + * Instantiates a new load folder event. + * + * @param selected the selected + */ + public LoadFolderEvent(Item selected) { + this.item = selected; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(LoadFolderEventHandler handler) { + handler.onLoadFolder(this); + } + + /** + * Gets the target folder. + * + * @return the target folder + */ + public Item getTargetFolder() { + return item; + } + + /** + * Sets the target folder. + * + * @param item the new target folder + */ + public void setTargetFolder(Item item) { + this.item = item; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEventHandler.java new file mode 100644 index 0000000..12120b0 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadFolderEventHandler.java @@ -0,0 +1,16 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + +/** + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * @May 23, 2013 + * + */ +public interface LoadFolderEventHandler extends EventHandler { + /** + * @param accountingHistoryEvent + */ + void onLoadFolder(LoadFolderEvent loadFolderEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEvent.java new file mode 100644 index 0000000..c50715a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEvent.java @@ -0,0 +1,35 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * + */ +public class LoadMySpecialFolderEvent extends GwtEvent { + + public static Type TYPE = new Type(); + + /** + * Instantiates a new double click event. + * + * @param target the target + */ + public LoadMySpecialFolderEvent() { + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(LoadMySpecialFolderEventHandler handler) { + handler.onLoadMySpecialFolder(this); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEventHandler.java new file mode 100644 index 0000000..6a181e4 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadMySpecialFolderEventHandler.java @@ -0,0 +1,21 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + + +/** + * The Interface LoadMySpecialFolderEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +public interface LoadMySpecialFolderEventHandler extends EventHandler { + + /** + * On load my special folder. + * + * @param loadMySpecialFolderEvent the load my special folder event + */ + void onLoadMySpecialFolder(LoadMySpecialFolderEvent loadMySpecialFolderEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEvent.java new file mode 100644 index 0000000..7dc1962 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEvent.java @@ -0,0 +1,33 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class LoadRootEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +public class LoadRootEvent extends GwtEvent { + + public static Type TYPE = new Type(); + + public LoadRootEvent() { + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(LoadRootEventHandler handler) { + handler.onLoadRoot(this); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEventHandler.java new file mode 100644 index 0000000..b0338c9 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/LoadRootEventHandler.java @@ -0,0 +1,20 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface LoadRootEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +public interface LoadRootEventHandler extends EventHandler { + + /** + * On load root. + * + * @param loadRootEvent the load root event + */ + void onLoadRoot(LoadRootEvent loadRootEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEvent.java new file mode 100644 index 0000000..baa14e3 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEvent.java @@ -0,0 +1,51 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.GwtEvent; + + + +/** + * The Class LoadFolderEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +public class OrderDataByEvent extends GwtEvent { + public static Type TYPE = new Type(); + private String label; + + /** + * Instantiates a new order data by event. + * + * @param label the label + */ + public OrderDataByEvent(String label) { + this.label = label; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(OrderDataByEventHandler handler) { + handler.onOrderDataBy(this); + } + + + /** + * @return the label + */ + public String getLabel() { + + return label; + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEventHandler.java new file mode 100644 index 0000000..2bf0e81 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/OrderDataByEventHandler.java @@ -0,0 +1,24 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + + +/** + * The Class OrderDataByEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 18, 2016 + */ +public interface OrderDataByEventHandler extends EventHandler { + + /** + * On load root. + * + * @param orderDataByEvent the label + */ + void onOrderDataBy(OrderDataByEvent orderDataByEvent); +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEvent.java new file mode 100644 index 0000000..6450330 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEvent.java @@ -0,0 +1,81 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class RightClickItemEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 23, 2016 + */ +public class RightClickItemEvent extends GwtEvent { + public static Type TYPE = new Type(); + private Item item; + private int xPos; + private int yPos; + + + /** + * Instantiates a new click item event. + * @param yPos + * @param xPos + * + * @param item the item + */ + public RightClickItemEvent(int xPos, int yPos, Item item) { + this.xPos = xPos; + this.yPos = yPos; + this.item = item; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + /** + * Dispatch. + * + * @param handler the handler + */ + @Override + protected void dispatch(RightClickItemEventHandler handler) { + handler.onClick(this); + } + + /** + * Gets the item. + * + * @return the item + */ + public Item getItem() { + return item; + } + + /** + * @return the xPos + */ + public int getXPos() { + + return xPos; + } + + + /** + * Gets the y pos. + * + * @return the yPos + */ + public int getYPos() { + + return yPos; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEventHandler.java new file mode 100644 index 0000000..9febd22 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RightClickItemEventHandler.java @@ -0,0 +1,21 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + +/** + * The Interface RightClickItemEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 23, 2016 + */ +public interface RightClickItemEventHandler extends EventHandler { + + + /** + * On click. + * + * @param rightClickItemEvent the right click item event + */ + void onClick(RightClickItemEvent rightClickItemEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEvent.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEvent.java new file mode 100644 index 0000000..611309c --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEvent.java @@ -0,0 +1,45 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.google.gwt.event.shared.GwtEvent; + +/** + * The Class LoadRootEvent. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +public class RootLoadedEvent extends GwtEvent { + + public static Type TYPE = new Type(); + private Item root; + + public RootLoadedEvent(Item root) { + this.root = root; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#getAssociatedType() + */ + @Override + public Type getAssociatedType() { + return TYPE; + } + + /* (non-Javadoc) + * @see com.google.gwt.event.shared.GwtEvent#dispatch(com.google.gwt.event.shared.EventHandler) + */ + @Override + protected void dispatch(RootLoadedEventHandler handler) { + handler.onRootLoaded(this); + } + + /** + * @return the root + */ + public Item getRoot() { + return root; + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEventHandler.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEventHandler.java new file mode 100644 index 0000000..3c62fdd --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/event/RootLoadedEventHandler.java @@ -0,0 +1,23 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.event; + +import com.google.gwt.event.shared.EventHandler; + + + +/** + * The Interface RootLoadedEventHandler. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Aug 3, 2015 + */ +public interface RootLoadedEventHandler extends EventHandler { + + + + /** + * On root loaded. + * + * @param rootLoadedEvent the root loaded event + */ + void onRootLoaded(RootLoadedEvent rootLoadedEvent); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/AbstractItemsCellTable.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/AbstractItemsCellTable.java new file mode 100644 index 0000000..4c2b199 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/AbstractItemsCellTable.java @@ -0,0 +1,196 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.grid; + +import java.util.List; +import java.util.Set; + +import org.gcube.portlets.user.workspaceexplorerapp.client.event.ClickItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.LoadFolderEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.RightClickItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.github.gwtbootstrap.client.ui.Pagination; +import com.google.gwt.core.shared.GWT; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.event.dom.client.ContextMenuEvent; +import com.google.gwt.event.dom.client.ContextMenuHandler; +import com.google.gwt.event.dom.client.DoubleClickEvent; +import com.google.gwt.event.dom.client.DoubleClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.cellview.client.DataGrid; +import com.google.gwt.user.cellview.client.HasKeyboardSelectionPolicy.KeyboardSelectionPolicy; +import com.google.gwt.user.cellview.client.SimplePager; +import com.google.gwt.user.client.Event; +import com.google.gwt.view.client.CellPreviewEvent; +import com.google.gwt.view.client.ListDataProvider; +import com.google.gwt.view.client.MultiSelectionModel; +import com.google.gwt.view.client.SelectionChangeEvent; +import com.google.gwt.view.client.SelectionChangeEvent.Handler; + +/** + * The Class AbstractItemTable. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Feb 19, 2015 + */ +public abstract class AbstractItemsCellTable { + + protected DataGrid dataGrid; + protected ListDataProvider dataProvider = new ListDataProvider(); + protected Item itemContextMenu = null; + protected boolean showMoreInfo; + protected final MultiSelectionModel msm; + protected final HandlerManager eventBus; + + /** + * Inits the table. + * + * @param ItemTable + * the Item table + * @param pager + * the pager + * @param pagination + * the pagination + */ + public abstract void initTable(final SimplePager pager, final Pagination pagination); + + + /** + * Instantiates a new abstract items cell table. + * + * @param eventBus the event bus + * @param fireOnClick the fire on click + */ + public AbstractItemsCellTable(HandlerManager eventBus, boolean fireOnClick) { + this.eventBus = eventBus; + this.showMoreInfo = fireOnClick; + dataGrid = new DataGrid(1); + dataGrid.getElement().setId("data_grid_explorer"); + dataGrid.getElement().setAttribute("id", "data_grid_explorer"); + dataGrid.setWidth("100%"); + dataGrid.setHeight("100%"); + dataProvider.addDataDisplay(dataGrid); + dataGrid.setKeyboardSelectionPolicy(KeyboardSelectionPolicy.ENABLED); + + msm = new MultiSelectionModel(); + dataGrid.setSelectionModel(msm); + msm.addSelectionChangeHandler(new Handler() { + @Override + public void onSelectionChange(final SelectionChangeEvent event) + { + final Set selectedObject = msm.getSelectedSet(); + GWT.log("Clicked: "+selectedObject); +// dataGrid.getRowContainer().removeClassName("dataGridSelectedRow"); + if(selectedObject!=null && !selectedObject.isEmpty()){ +// GWT.log("Current Selected Row : "+ dataGrid.getKeyboardSelectedRow()); +// dataGrid.getRowElement(dataGrid.getKeyboardSelectedRow()).addClassName("dataGridSelectedRow"); +// selectedItem(selectedObject); + if(showMoreInfo) + AbstractItemsCellTable.this.eventBus.fireEvent(new ClickItemEvent(selectedObject)); + } + } + }); + + dataGrid.addDomHandler(new DoubleClickHandler() { + + @Override + public void onDoubleClick(final DoubleClickEvent event) { + Set selected = msm.getSelectedSet(); + GWT.log("Double Click: "+selected); + if (selected != null && !selected.isEmpty()) { + AbstractItemsCellTable.this.eventBus.fireEvent(new LoadFolderEvent(selected.iterator().next())); + } + } + }, + DoubleClickEvent.getType()); + + dataGrid.addDomHandler(new ContextMenuHandler() { + + @Override + public void onContextMenu(ContextMenuEvent event) { + event.preventDefault(); + event.stopPropagation(); + } + }, ContextMenuEvent.getType()); + + + dataGrid.addCellPreviewHandler(new CellPreviewEvent.Handler() { + + @Override + public void onCellPreview(CellPreviewEvent event) { +// GWT.log("CellPreview click"); + if (event.getNativeEvent().getButton() == NativeEvent.BUTTON_RIGHT && event.getNativeEvent().getType().equals("contextmenu")) { + event.getNativeEvent().preventDefault(); + event.getNativeEvent().stopPropagation(); +// int clickedRow = event.getIndex(); + Item item = event.getValue(); + GWT.log("Right click on "+ item); + AbstractItemsCellTable.this.eventBus.fireEvent(new RightClickItemEvent(event.getNativeEvent().getClientX(), event.getNativeEvent().getClientY(), item)); + event.setCanceled(true); + } + } + }); + + /*MenuBar options = new MenuBar(true); + ScheduledCommand openCommand = new ScheduledCommand() { + + @Override + public void execute() { + AbstractItemsCellTable.this.eventBus.fireEvent(new LoadFolderEvent(itemContextMenu)); + } + }; + + MenuItem openItem = new MenuItem("Open", openCommand); + options.addItem(openItem); + final DialogBox menuWrapper = new DialogBox(true); + menuWrapper.getElement().getStyle().setBorderStyle(BorderStyle.NONE); + menuWrapper.getElement().getStyle().setZIndex(10000); + menuWrapper.add(options);*/ + dataGrid.sinkEvents(Event.ONCONTEXTMENU); + } + + + /** + * Update items. + * + * @param items the items + * @param removeOldItems the remove old items + */ + public void updateItems(List items, boolean removeOldItems) { + + if(removeOldItems){ + dataProvider.getList().clear(); + msm.clear(); + } + + dataProvider.getList().addAll(items); + dataGrid.setPageSize(items.size()+1); + dataGrid.redraw(); + } + + /** + * Gets the cell tables. + * + * @return the cell tables + */ + public DataGrid getCellTable() { + return dataGrid; + } + + /** + * Gets the data provider. + * + * @return the data provider + */ + public ListDataProvider getDataProvider() { + return dataProvider; + } + + /** + * Sets the data provider. + * + * @param dataProvider + * the new data provider + */ + public void setDataProvider(ListDataProvider dataProvider) { + this.dataProvider = dataProvider; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/DisplayField.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/DisplayField.java new file mode 100644 index 0000000..1391bc0 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/DisplayField.java @@ -0,0 +1,84 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.grid; + + +/** + * The Enum DisplayField. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 18, 2016 + */ +public enum DisplayField { + + ICON("Icon", true, false), + NAME("Name", true, true), + OWNER("Owner", true, true), + CREATION_DATE("Creation Date", false, true); + + + private String label; + private boolean isSortable; + private boolean showIntable; + /** + * Instantiates a new display field. + * + * @param id the id + * @param isSortable the is sortable + */ + private DisplayField(String label, boolean showInTable, boolean isSortable) { + this.label = label; + this.isSortable = isSortable; + this.showIntable = showInTable; + } + + /** + * @return the label + */ + public String getLabel() { + + return label; + } + + /** + * @return the isSortable + */ + public boolean isSortable() { + + return isSortable; + } + + /** + * @return the showIntable + */ + public boolean isShowIntable() { + + return showIntable; + } + + /** + * @param label the label to set + */ + public void setLabel(String label) { + + this.label = label; + } + + /** + * @param isSortable the isSortable to set + */ + public void setSortable(boolean isSortable) { + + this.isSortable = isSortable; + } + + /** + * @param showIntable the showIntable to set + */ + public void setShowIntable(boolean showIntable) { + + this.showIntable = showIntable; + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/ItemsTable.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/ItemsTable.java new file mode 100644 index 0000000..4881f20 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/ItemsTable.java @@ -0,0 +1,399 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.grid; + +import gwt.material.design.client.base.MaterialImageCell; +import gwt.material.design.client.constants.IconPosition; +import gwt.material.design.client.constants.IconType; +import gwt.material.design.client.constants.ImageType; +import gwt.material.design.client.ui.MaterialIcon; +import gwt.material.design.client.ui.MaterialImage; + +import java.util.Arrays; +import java.util.Comparator; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.gcube.portlets.user.workspaceexplorerapp.client.Util; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.LoadFolderEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.view.PopupContextMenu; +import org.gcube.portlets.user.workspaceexplorerapp.client.view.SelectionItem; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.github.gwtbootstrap.client.ui.Pagination; +import com.google.gwt.cell.client.ButtonCell; +import com.google.gwt.cell.client.Cell.Context; +import com.google.gwt.cell.client.DateCell; +import com.google.gwt.cell.client.SafeHtmlCell; +import com.google.gwt.core.shared.GWT; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.safehtml.shared.SafeHtml; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; +import com.google.gwt.safehtml.shared.SafeHtmlUtils; +import com.google.gwt.user.cellview.client.Column; +import com.google.gwt.user.cellview.client.ColumnSortEvent; +import com.google.gwt.user.cellview.client.ColumnSortEvent.ListHandler; +import com.google.gwt.user.cellview.client.ColumnSortList.ColumnSortInfo; +import com.google.gwt.user.cellview.client.SimplePager; +import com.google.gwt.user.cellview.client.TextColumn; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.Label; +/** + * The Class PackagesTable. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 19, 2015 + */ +public class ItemsTable extends AbstractItemsCellTable implements SelectionItem{ + + private DateTimeFormat dateFormatter = DateTimeFormat.getFormat("dd MMM hh:mm aaa yyyy"); + + /** + * The Enum DISPLAY_FIELD. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 1, 2016 + */ +// public static enum DISPLAY_FIELD{ICON, NAME, OWNER}; + private List displayFields; + + private Map mapFieldToColumnIndex = new HashMap(); + + private Column dateColumn; + + /** + * Instantiates a new items table. + * + * @param eventBus the event bus + * @param showMoreInfo the show more info + * @param fields the fields + */ + public ItemsTable(HandlerManager eventBus, boolean showMoreInfo, DisplayField[] fields) { + super(eventBus, showMoreInfo); + setDisplayFields(fields); + initTable(null, null); + + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.view.grid.AbstractItemsCellTable#updateItems(java.util.List, boolean) + */ + public void updateItems(List items, boolean removeOldItems) { + super.updateItems(items, removeOldItems); + } + + /** + * Adds the items. + * + * @param items the items + */ + public void addItems(List items) { + if(items!=null) + dataProvider.getList().addAll(items); + } + + /* (non-Javadoc) + * @see org.gcube.portlets.admin.gcubereleases.client.view.AbstractPackageTable#initTable(com.google.gwt.user.cellview.client.AbstractCellTable, com.google.gwt.user.cellview.client.SimplePager, com.github.gwtbootstrap.client.ui.Pagination) + */ + @Override + public void initTable(final SimplePager pager, final Pagination pagination) { + dataGrid.setEmptyTableWidget(new Label("No data.")); + + if(this.displayFields.contains(DisplayField.ICON)){ + + MaterialImageCell myIcon = new MaterialImageCell(){ + public Set getConsumedEvents() { + HashSet events = new HashSet(); + events.add("click"); + return events; + } + }; + + // IMAGE + Column icon = new Column(myIcon) { + @Override + public MaterialImage getValue(final Item object) { + MaterialImage img = new MaterialImage(); + img.setUrl(Util.getImageResource(object).getSafeUri().asString()); + img.setWidth("32px"); + img.setHeight("32px"); + img.setType(ImageType.DEFAULT); + + if(object.isFolder()){ + img.addStyleName("navigation-cursor"); + } + + return img; + } + + public void onBrowserEvent(com.google.gwt.cell.client.Cell.Context context, Element elem, Item object, NativeEvent event) { + super.onBrowserEvent(context, elem, object, event); + GWT.log("onBrowserEvent ON IMG "+event.getType()); + // Handle the click event. + if ("click".equals(event.getType())) { + if(object.isFolder()){ + GWT.log("clicked folder onBrowserEvent "+object); + eventBus.fireEvent(new LoadFolderEvent(object)); + } + } + }; + }; + + icon.setSortable(false); +// packageTable.addColumn(icon, ""); + dataGrid.addColumn(icon); + dataGrid.setColumnWidth(icon, "45px"); + } + + Column nameColumn; + if(this.displayFields.contains(DisplayField.NAME)){ + + final SafeHtmlCell progressCell = new SafeHtmlCell(); + + nameColumn = new Column(progressCell) { + + @Override + public SafeHtml getValue(Item object) { + SafeHtmlBuilder sb = new SafeHtmlBuilder(); + sb.appendHtmlConstant("
"); + sb.appendHtmlConstant(object.getName()); + String formatDate = dateFormatter.format(object.getCreationDate()); + String tooltipDate = "Created: "+formatDate; + sb.appendHtmlConstant("
"); + sb.appendHtmlConstant(formatDate); + sb.appendHtmlConstant("
"); + return sb.toSafeHtml(); + } + }; + + nameColumn.setSortable(true); + ListHandler nameColumnHandler = new ListHandler(dataProvider.getList()); + nameColumnHandler.setComparator(nameColumn, new Comparator() { + @Override + public int compare(Item o1, Item o2) { + + if(o1==null) + return 1; + else if(o2==null) + return -1; + + //XOR + if (o1.isSpecialFolder() ^ o2.isSpecialFolder()) return o1.isSpecialFolder() ? -1 : 1; + if (o1.isFolder() ^ o2.isFolder()) return o1.isFolder() ? -1 : 1; + + return String.CASE_INSENSITIVE_ORDER.compare(o1.getName(), o2.getName()); + } + }); + + dataGrid.addColumnSortHandler(nameColumnHandler); + dataGrid.addColumn(nameColumn); + mapFieldToColumnIndex.put(DisplayField.NAME.getLabel(), dataGrid.getColumnIndex(nameColumn)); + dataGrid.getColumnSortList().push(nameColumn); + } + + if(this.displayFields.contains(DisplayField.OWNER)){ + + TextColumn owner = new TextColumn() { + @Override + public String getValue(Item object) { + return object.getOwner() != null ? object.getOwner() : ""; + } + }; + + owner.setSortable(true); + ListHandler ownerColumnHandler = new ListHandler(dataProvider.getList()); + ownerColumnHandler.setComparator(owner, new Comparator() { + @Override + public int compare(Item o1, Item o2) { + + if(o1==null) + return 1; + else if (o2==null) + return -1; + + return o1.getOwner().compareTo(o2.getOwner()); + } + }); + + dataGrid.addColumnSortHandler(ownerColumnHandler); + dataGrid.addColumn(owner); + mapFieldToColumnIndex.put(DisplayField.OWNER.getLabel(), dataGrid.getColumnIndex(owner)); + } + + + if(this.displayFields.contains(DisplayField.CREATION_DATE)){ + + DateCell dateCell = new DateCell(); + dateColumn = new Column(dateCell) { + @Override + public Date getValue(Item object) { + return object.getCreationDate(); + } + }; + + dateColumn.setSortable(true); + ListHandler dateColumnHandler = new ListHandler(dataProvider.getList()); + dateColumnHandler.setComparator(dateColumn, new Comparator() { + @Override + public int compare(Item o1, Item o2) { + return o1.getCreationDate().compareTo(o2.getCreationDate()); + } + }); + + dataGrid.addColumnSortHandler(dateColumnHandler); +// dataGrid.addColumn(dateColumn); +// mapFieldToColumnIndex.put(DisplayField.CREATION_DATE.getLabel(), dataGrid.getColumnIndex(dateColumn)); + } + + + Column moreColumn = new Column(new MaterialIconCell()){ + + @Override + public MaterialIcon getValue(final Item object) { + MaterialIcon button = new MaterialIcon(); + button.setIconColor("black"); + button.setWidth("15px"); +// button.setWaves(WavesType.DEFAULT); + button.setIconPosition(IconPosition.RIGHT); + button.getElement().getStyle().setMarginRight(17.0,Unit.PX); + button.setIconType(IconType.MORE_VERT); + return button; + } + + /* (non-Javadoc) + * @see com.google.gwt.user.cellview.client.Column#onBrowserEvent(com.google.gwt.cell.client.Cell.Context, com.google.gwt.dom.client.Element, java.lang.Object, com.google.gwt.dom.client.NativeEvent) + */ + @Override + public void onBrowserEvent(Context context, Element elem, Item object, NativeEvent event) { + + + // Handle the click event. + if ("click".equals(event.getType())) { + //skip right click + if (event.getButton() == NativeEvent.BUTTON_RIGHT) { + return; + } + PopupContextMenu popupCM = new PopupContextMenu(true, eventBus, object); + popupCM.showPopup(event.getClientX()-100, Window.getScrollTop()+event.getClientY()); + } + } + + }; + moreColumn.setSortable(false); +// packageTable.addColumn(moreColumn, ""); + dataGrid.addColumn(moreColumn); + dataGrid.setColumnWidth(moreColumn, "50px"); + } + + /** + * Sets the display fields. + * + * @param fields the new display fields + */ + public void setDisplayFields(DisplayField[] fields) { + this.displayFields = fields!=null && fields.length>0?Arrays.asList(fields):Arrays.asList(DisplayField.values()); + } + + /** + * Gets the display fields. + * + * @return the displayFields + */ + public List getDisplayFields() { + return displayFields; + } + + /** + * The Class ButtonImageCell. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 1, 2016 + */ + public class ButtonImageCell extends ButtonCell{ + + /* (non-Javadoc) + * @see com.google.gwt.cell.client.AbstractSafeHtmlCell#render(com.google.gwt.cell.client.Cell.Context, java.lang.Object, com.google.gwt.safehtml.shared.SafeHtmlBuilder) + */ + @Override + public void render(com.google.gwt.cell.client.Cell.Context context, + String value, SafeHtmlBuilder sb) { + SafeHtml html = SafeHtmlUtils.fromTrustedString(new Image(value).toString()); + sb.append(html); + } + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.notification.SelectionItemHandler#getSelectionItem() + */ + @Override + public Set getSelectedItems() { + Set items = msm.getSelectedSet(); + + if(items==null || items.isEmpty()) + return null; + + return items; + } + + /** + * @param label + */ + public void sortDataBy(String label) { + GWT.log("sort by "+label); + boolean isAscending = true; + if(this.dataGrid.getColumnSortList().size()>0) + isAscending = this.dataGrid.getColumnSortList().get(0).isAscending(); + + boolean removeDateColumn = false; + if(label.compareTo(DisplayField.CREATION_DATE.getLabel())==0){ + dataGrid.addColumn(dateColumn); + mapFieldToColumnIndex.put(DisplayField.CREATION_DATE.getLabel(), dataGrid.getColumnIndex(dateColumn)); + removeDateColumn = true; + } + + int colIndex = mapFieldToColumnIndex.get(label); + + GWT.log("colIndex " + colIndex); + GWT.log("isAscending " + isAscending); + if(colIndex>-1){ + Column column = this.dataGrid.getColumn(colIndex); + if (column != null && column.isSortable()) { + this.dataGrid.getColumnSortList().clear(); + setSortedColumn(column, !isAscending); + ColumnSortEvent.fire(dataGrid, dataGrid.getColumnSortList()); + + if(removeDateColumn) + dataGrid.removeColumn(colIndex); + } + } + } + + /** + * Displays the appropriate sorted icon in the header of the column for the given index. + * + * @param columnIndex + * of the column to mark as sorted + * @param ascending + * true for ascending icon, false for descending icon + */ + public void setSortedColumn(Column column, boolean ascending) { + + if (column != null && column.isSortable()) { + ColumnSortInfo info = this.dataGrid.getColumnSortList().push(column); + GWT.log("ColumnSortInfo is anscending "+info.isAscending()); + if (info.isAscending() != ascending) { + this.dataGrid.getColumnSortList().push(column); + } + } + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MaterialIconCell.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MaterialIconCell.java new file mode 100644 index 0000000..c9c61f6 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MaterialIconCell.java @@ -0,0 +1,61 @@ +/** + * + */ + +package org.gcube.portlets.user.workspaceexplorerapp.client.grid; + +import gwt.material.design.client.ui.MaterialIcon; + +import com.google.gwt.cell.client.AbstractCell; +import com.google.gwt.cell.client.ValueUpdater; +import com.google.gwt.dom.client.Element; +import com.google.gwt.dom.client.NativeEvent; +import com.google.gwt.safehtml.shared.SafeHtmlBuilder; + +/** + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Mar 8, 2016 + */ +public class MaterialIconCell extends AbstractCell { + + /** + * + */ + public MaterialIconCell() { + + /* + * Sink the click and keydown events. We handle click events in this + * class. AbstractCell will handle the keydown event and call + * onEnterKeyDown() if the user presses the enter key while the cell is + * selected. + */ + super("click", "keydown"); + } + + @Override + public void render( + com.google.gwt.cell.client.Cell.Context context, MaterialIcon value, + SafeHtmlBuilder sb) { + + if(value==null) + return; + + sb.appendHtmlConstant(value.getElement().getString()); + } + + /** + * Called when an event occurs in a rendered instance of this Cell. The + * parent element refers to the element that contains the rendered cell, NOT + * to the outermost element that the Cell rendered. + */ + + /* (non-Javadoc) + * @see com.google.gwt.cell.client.AbstractCell#onBrowserEvent(com.google.gwt.cell.client.Cell.Context, com.google.gwt.dom.client.Element, java.lang.Object, com.google.gwt.dom.client.NativeEvent, com.google.gwt.cell.client.ValueUpdater) + */ + @Override + public void onBrowserEvent( + com.google.gwt.cell.client.Cell.Context context, Element parent, + MaterialIcon value, NativeEvent event, + ValueUpdater valueUpdater) { + super.onBrowserEvent(context, parent, value, event, valueUpdater); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.java new file mode 100644 index 0000000..356525a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.java @@ -0,0 +1,93 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.grid; + +import gwt.material.design.client.ui.MaterialLink; + +import org.gcube.portlets.user.workspaceexplorerapp.client.download.DownloadType; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.DownloadItemEvent; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemInterface; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + + +/** + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 8, 2016 + */ +public class MenuMoreOptionsOnItem extends Composite { + + private static MenuMoreOptionsOnItemUiBinder uiBinder = + GWT.create(MenuMoreOptionsOnItemUiBinder.class); + + interface MenuMoreOptionsOnItemUiBinder + extends UiBinder { + } + + @UiField + MaterialLink open; + + @UiField + MaterialLink download; + + private HandlerManager eventBus; + + private ItemInterface itemToDownload; + + private Command commandOnClick; + + public MenuMoreOptionsOnItem(HandlerManager eventBus) { + initWidget(uiBinder.createAndBindUi(this)); + + this.eventBus = eventBus; + download.addClickHandler(new ClickHandler() { + + /* (non-Javadoc) + * @see com.google.gwt.event.dom.client.ClickHandler#onClick(com.google.gwt.event.dom.client.ClickEvent) + */ + @Override + public void onClick(ClickEvent event) { + + MenuMoreOptionsOnItem.this.eventBus.fireEvent(new DownloadItemEvent(itemToDownload, DownloadType.DOWNLOAD)); + GWT.log("commandOnClick " + commandOnClick); + if(commandOnClick!=null) + commandOnClick.execute(); + } + }); + + open.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + MenuMoreOptionsOnItem.this.eventBus.fireEvent(new DownloadItemEvent(itemToDownload, DownloadType.OPEN)); + GWT.log("commandOnClick " + commandOnClick); + if(commandOnClick!=null) + commandOnClick.execute(); + } + }); + + } + + + /** + * Inits the on item. + * + * @param itemToDownload the item to download + * @param commandOnClick the command on click + */ + public void initOnItem(ItemInterface itemToDownload, Command commandOnClick){ + this.itemToDownload = itemToDownload; + this.commandOnClick = commandOnClick; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.ui.xml b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.ui.xml new file mode 100644 index 0000000..16374ed --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/grid/MenuMoreOptionsOnItem.ui.xml @@ -0,0 +1,19 @@ + + + + .onHoverUnderline :HOVER{ + text-decoration: underline; + } + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.css b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.css new file mode 100644 index 0000000..1dad65c --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.css @@ -0,0 +1,7 @@ +/* @url */ +@url invalidNameUrl invalidName; + +.nameError{ + background:#fff invalidNameUrl repeat-x bottom; + border: 1px solid #dd7870; +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.java new file mode 100644 index 0000000..97bcf0e --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerAppCss.java @@ -0,0 +1,23 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.resources; + +import com.google.gwt.resources.client.CssResource; + +/** + * The Interface WorkspaceLightTreeCss. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 8, 2015 + */ +public interface WorkspaceExplorerAppCss extends CssResource { + + /** + * Name error. + * + * @return the string + */ + public String nameError(); + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerResources.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerResources.java new file mode 100644 index 0000000..ce1207b --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceExplorerResources.java @@ -0,0 +1,36 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.resources; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.ImageResource; + +/** + * The Interface WorkspaceLightTreeResources. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 8, 2015 + */ +public interface WorkspaceExplorerResources extends ClientBundle { + + public static final WorkspaceExplorerResources INSTANCE = GWT.create(WorkspaceExplorerResources.class); + + /** + * Root. + * + * @return the image resource + */ + @Source("_32/folder.png") + ImageResource folder(); + + /** + * Folder. + * + * @return the image resource + */ + @Source("_32/groups_folder.png") + ImageResource shared_folder(); + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceLightTreeResources.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceLightTreeResources.java new file mode 100644 index 0000000..7006fbf --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/WorkspaceLightTreeResources.java @@ -0,0 +1,245 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.resources; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.DataResource; +import com.google.gwt.resources.client.ImageResource; + +/** + * The Interface WorkspaceLightTreeResources. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jul 8, 2015 + */ +public interface WorkspaceLightTreeResources extends ClientBundle { + + public static final WorkspaceLightTreeResources INSTANCE = GWT.create(WorkspaceLightTreeResources.class); + + /** + * Root. + * + * @return the image resource + */ + @Source("root.png") + ImageResource root(); + + /** + * Folder. + * + * @return the image resource + */ + @Source("folder.png") + ImageResource folder(); + + /** + * Shared folder. + * + * @return the image resource + */ + @Source("shared_folder.png") + ImageResource sharedFolder(); + + /** + * External_image. + * + * @return the image resource + */ + @Source("external_image.gif") + ImageResource external_image(); + + /** + * External_pdf. + * + * @return the image resource + */ + @Source("external_pdf.gif") + ImageResource external_pdf(); + + /** + * External_file. + * + * @return the image resource + */ + @Source("external_file.png") + ImageResource external_file(); + + /** + * External_resource_link. + * + * @return the image resource + */ + @Source("external_resource_link.png") + ImageResource external_resource_link(); + + /** + * External_url. + * + * @return the image resource + */ + @Source("external_url.png") + ImageResource external_url(); + + /** + * Report_template. + * + * @return the image resource + */ + @Source("report_template.png") + ImageResource report_template(); + + /** + * Report. + * + * @return the image resource + */ + @Source("report.png") + ImageResource report(); + + /** + * Query. + * + * @return the image resource + */ + @Source("query.png") + ImageResource query(); + + /** + * Document. + * + * @return the image resource + */ + @Source("document.png") + ImageResource document(); + + /** + * Metadata. + * + * @return the image resource + */ + @Source("metadata.png") + ImageResource metadata(); + + /** + * Pdf_document. + * + * @return the image resource + */ + @Source("pdf_document.png") + ImageResource pdf_document(); + + /** + * Image_document. + * + * @return the image resource + */ + @Source("image_document.png") + ImageResource image_document(); + + /** + * Url_document. + * + * @return the image resource + */ + @Source("url_document.png") + ImageResource url_document(); + + /** + * Timeseries. + * + * @return the image resource + */ + @Source("timeseries.png") + ImageResource timeseries(); + + /** + * Aquamaps. + * + * @return the image resource + */ + @Source("aquamaps.png") + ImageResource aquamaps(); + + /** + * Workflow_report. + * + * @return the image resource + */ + @Source("workflow_report.png") + ImageResource workflow_report(); + + /** + * Workflow_template. + * + * @return the image resource + */ + @Source("workflow_template.png") + ImageResource workflow_template(); + + /** + * Unknown type. + * + * @return the image resource + */ + @Source("noimage.png") + ImageResource unknownType(); + + /** + * Loading. + * + * @return the image resource + */ + @Source("ajax-loader.gif") + ImageResource loading(); + + /** + * Gucbe item. + * + * @return the image resource + */ + @Source("gcubeItem.jpeg") + ImageResource gucbeItem(); + + + /** + * Unknown. + * + * @return the image resource + */ + @Source("icon-unknown.gif") + ImageResource unknown(); + + /** + * Invalid name. + * + * @return the data resource + */ + @Source("invalid_name.gif") + DataResource invalidName(); + + /** + * Css. + * + * @return the workspace light tree css + */ + @Source("WorkspaceExplorerAppCss.css") + WorkspaceExplorerAppCss css(); + + /** + * Error. + * + * @return the image resource + */ + @Source("error.png") + ImageResource error(); + + /** + * Refresh. + * + * @return the image resource + */ + @Source("refresh.png") + ImageResource refresh(); +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/_32/folder.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/_32/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..a0057c2f7c5bb6c6f54223b7a76903cc4ff14c53 GIT binary patch literal 1250 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 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/ajax-loader.gif b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/ajax-loader.gif new file mode 100644 index 0000000000000000000000000000000000000000..d0bce1542342e912da81a2c260562df172f30d73 GIT binary patch literal 673 zcmZ?wbhEHb6krfw_{6~Q|Nnmm28Kh24mmkF0U1e2Nli^nlO|14{Lk&@8WQa67~pE8 zXTZz|lvDgC+Z`3#dv5h=E26FfcG1 zbL_hF&)}42ws10s6^G;;cE1^EoUR)U5A70}d2pLv!jVIT7j&Z~EblI3x0K*v_sV|m z0kj3v921Z^em#l`(k(o@H$3ZdDRc@9NidXDNbqrumReCGv$gd8+e8WW28HVqkJ_9i zH>s*<31KtHjANIPvi2#*6BEu%3Dak5O_t&NBI)H?V$TxT}#l{vOTn5naXTfF^&~Hhq+NX@#Ccc>y7T?;vjI&jdhsDsPJyAw*m0Qz>i}K7# zL9w50Ng{fT}A5JUe8lRK1h7_Y2;BWJDd=c6f&i?Wv5(5q?6|P zQw{>maxZP<537OA37Uk}7@%_$4o$EWe_Zl>&#id|lE-BpDC#+Fn|msJ%_2h{Hg1vP z#N8WAzfWasG}yq|xqE)DrWaOofX=z|?*pgc%{ig5vl!pqDlC|q&~Z0$&Rvsft&VO- z4MZj+%-+Vx%W}v;V76hyp=;+R;x+~t^Q%*xuFTQAF2})fSfTHDAs>sO!OBw`)&)o$ c0!CNZt))x~rAZP^^P&YOFfdqy5)K#u0POD40{{R3 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/aquamaps.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/aquamaps.png new file mode 100644 index 0000000000000000000000000000000000000000..25a4da60cb90b7bd5c8181a70b71d7cecddebbf6 GIT binary patch literal 980 zcmV;_11tQAP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2iXe= z4k;=BSF=$7000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}0009oNkl|Z)ntY9LHau@9+1!-S7VGcCwXojZ$Zhi`{C)1zPNZN*HA7gZU)zfk+gK9)(Cj zP(A5sK~y-2pr{^68M>0466$n?@4Vm6+uiT>`}6IQFzfy3{f5^Y-cR1b ze{|yaQ~5~!&igl?+`6yTbWpJv_Wcq$!zolGdg!$`c22J5Wp(&r?C9mbn4kM`!3QxI z=-?~V>W>ZnKN$fqAquX%d?z?VTkL9~N6pG`4Y2FLDY zn={6S;so)`8a57Q2fqLOv+2hc9Q*Fu%RPO41GQ*E8aIwHo*bdNHp}|T1j(x>**ssz z-0~{PR2B&W^=f);*xd)!kZd5kwAwbiU7OfP^17|&OiTjw{YEy@jtpRH{Kb{Y|lr%jeZh@0?o z={Q4alOPCLXeo}ip5v$9#rM>X?K>u`<;t`+lG5kU}?fQX{kyGM+WYpO?k%Yhs| zxNG-gUwG?-!@0Rx?@FcFz%)%v1)woRP%5OD?BnZ)>-5zdE0;dpmFuB$d*Od?1aPJ< zj(&BQJ%QaZ{4n&C#5QQ<|d}62BjvZR2H60wE-&H;pyTSqH(@-Vl>|&1p(LP>kg~E zYiz5X^`c$+%8#zC{u)yfe-5 zmgid={Z3k(ERKCKrE7DF;=x4^O+ pzO8rLO8p|Ip=x)jHOtWj`bJBmKdh_V<`47(gQu&X%Q~loCIFbEay|e6 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/error.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/error.png new file mode 100644 index 0000000000000000000000000000000000000000..628cf2dae3d419ae220c8928ac71393b480745a3 GIT binary patch literal 666 zcmV;L0%iS)P)eOSYYtbpBV}~vsBnU!_?2tr-P=|^T zED%wc9ezHgW@NMb!^uT_|SvCpFLJylbx zY%bpaTGI8IYXMN$9w<3j9VkA~NYOKEQXsj?6a9_hcwfU$acAhJhB)zb_w@MVUEy@S zX&I>K-R!bhu3?(6bHWIg$HEl7{9g>>&l_qdd+UYb(1~BCo9LptNq&8>!yoJ3Ui(i5 zRJ|XnYBklL!{@$-7=3mJ>P@1c=7Oc79e-V7yf+%lD2!I;Y&nXBZ>=B!5?CB>LvEx6 znI%n)qqi$#X#wKB(U7XP2P=+4{b@j#r%9-K(8UqtSDk>0UKzf*HM9yqMZ1D!$2MdZ zR=`U>0zhOH1XqN?nY@AQqB7)Fp4{v&dKXvb43hZKvnN8;Po;+jY*}~*Z|W9Q0W%{D z^T}Cc<|r(Su=1K=P5>Z4 zg`et&Va}tdzBS-G-ZcO)zCWpJvGQwrHZ`@wpM420ac@bI5~KkTFfGEM3sPWO8co4^fI6lPnA)Y{ef%@{+SnoUk0+dW+*{8WvF8}}l07*qoM6N<$g7cXs A&j0`b literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_file.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_file.png new file mode 100644 index 0000000000000000000000000000000000000000..1dee9e366094e87db68c606d0522d72d4b939818 GIT binary patch literal 464 zcmV;>0WbcEP)8e6`gpm!y1M!N^ZV(=IC*t) z{^;nqJv-tM$9J1L2QJ2DN!#51=1_l@G`2=6e0lehL%sic%`_4--LFM}IF!KzJCseW zq1I3__Z40|e?qyK1__gzP(qrBf-G7SQbQ`#Lw94WVe(o`qg+f4hy;Qju)q#I(9{`% zQmAGomzhQ!b|gq>KqL@IkO~$=Koi}a$u6d07kiS}NoYVMJjAeZpaB*;wwcDdEbK@K zNP;B7RzhQ|H9AlUO<`J>m1(5R)Pb-iLBb@7Jp)}LHdAb-VVgYxVoTzGoqu{~a>6uj zeqCRFI9pC#h09bGwy9;oHcp6(RB%jeY^F=Ll!S+9JkVe4nDG7tJMQiP000037$;T>| z-6~r4sBH7AO(sHXjdZ&r3^qp^uFO#1TJCznRN|7O>`hO_XW{C9a*h8Mo3)oN-QJwP zr?dKXtL5)z>)R6}PfRYkJh$-r(y~XBg8y_m|7{ETG1c|&)U>}Vg8puc{IVe5Nmx6hcoa>|P4*(aw?Kit0ROxubZlb4^K zvGnTVJx^C}{4wp=_ob)5thn@d_o-joum3$Td+Lqt&CgCW{=Ylx=hN21*Zy3-`~29W ze|Mj}zWVat(`V0LzWwy#^WR^8{(k-XAME>4Vnm04;!hT428Lh;9Z)EM@&p6NA%^8X zHyt-5I5IH_^G!LlVc`^6J^`&e4>u$>v2dtxEr~Gf5>mD2%UIH()Z8Yd8Rb&=DCLBQ zrkYBI#X_deZV{UpwIv*i2b#IW3=(!UI6pt8p`zsT;X~q4c7CfKz80gVCI$hOxIGLT zowfSZU9ET?C_Lim7T{T;mr<1L%qZnP>A;4A3LS2&zC}l77%pxT6f>5(;aic=DXi$! w#KL$eqJzJ;b*{lopCv|*j&t&UxpAl2z3;qb%8?5etqm_PukiKfZ_06kHnWap<7OBvt+eEdc_D z7^bily*hJJ(V2}?l1V{lfnqZoFONxqMOMg*152gsOddFF)nH$)z@_taLtEgpSdQ4~@C*Y~p4WKQ1&jF>myL-n4YrmX`tS{A}{6s}8<< Xu&QUHkc30z0R~1Uri^Pc0u0swR-=G& literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_resource_link.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_resource_link.png new file mode 100644 index 0000000000000000000000000000000000000000..6224d01a0edb5810f1b2d5556cacb2506eb7b4d1 GIT binary patch literal 855 zcmV-d1E~CoP)^lNY}(c6#>C4rce^{k-ipOy3x;7JrHtfq zxvqE-FmiI|uG&}q`orlA!-+V$7)4XvSg~e~ZTw{}#B`nc`FU1XS1FZBH-P)k0bhN; z_T9w`?$W!L&Jj_L2!lEb5p*#`Iu+sSd5gy_9nbR!f&gF`KmaVSJiL>6HMMko`V}hH zBZzi!q=y#7DR=TX6`jrBHc2LvwA*cb-$zlDZ?oBKNn2idIHGFm{SU63MZvubF2RK+9Zg!X$%TTY^866#^SS&I=K2EJx8&HA8zW5oM?h~F`4`?T=*wHd!tVZ28 zs5HyCc9%pVfoYm-ZEewLG#DNp2AC4SOr)=uR_LL49xbs)Z=i7O9@7ynUH>u)DpE=Y z2M5_bYBN1Ki4dpr37|g+0+gP!^hT0wAN)d3(uVpJA^i;WU!W5{LrRGd0!t>*^&V7J z1waL!*>;=8iKHrr=yq^cBgmPN)dvcJENloCLyz?yBj6e`D* znm$V6Q>0wx!Tt}drT9SDx%za^!ZuoXMiZ}mM5mgnl zY%)1CMJkn|QmNoL&X>7d?i2u^{c!O*;y?N!>E+<;`o)1KItDEdk0mGDBwGd%A>=r-+#RP=4+!u hh|ht0xm<1y;9r7(e~Qz7fGYq1002ovPDHLkV1n07kSzcJ literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_url.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/external_url.png new file mode 100644 index 0000000000000000000000000000000000000000..25eacb7c2524142262d68bf729c5e2b61adfd6d4 GIT binary patch literal 343 zcmV-d0jU0oP)$`dXYaZs9=SbAto%g@>T~?_bH&lTUn@`uo|1bXE{eSR(AO)ESb=V4`uk}mK|39Px&03WLbv~pzk+s7D@lK^ zn+aB+sp)&Y_x-B3>;6ywU--WQNUr<8>TU0P-|L#1U&;A)67w(+> pDf@fM7q9#F25QXo3rUI;002ro52U44e~JJA002ovPDHLkV1l;_q@Mr) literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/folder.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/folder.png new file mode 100644 index 0000000000000000000000000000000000000000..784e8fa48234f4f64b6922a6758f254ee0ca08ec GIT binary patch literal 537 zcmV+!0_OdRP)x(K@^6+>g^d@v4;gkbWsEoXE%32*i1tcpTNXd5CcIl)ECgqz|2rE6EW}s7R?kl za1q`0GCkMruC6-2LANtwVlsgzsp4?{@7$`KBv!G66>Vie3h?3OmEEkjwdLG0PgLVi z`!N((f$A@n17Ldj#`};0I3@iHJ5M{#IZz|UIYRm4(!uV7eYIYIwQf&}_2J~}>pQ^n z6o8--^T(=hkBNQ_k{-_GWE;FMW7!p}f{NG3nHZ{D5<3d8&tLh%a4AqqnjMkr3m&fkMdECD3N5}Unig5wy40;>lo4j~k+e}v)` zR6)J8Mk*u=SpB`p6o)7j?S0T@9?bz#m@l>gc*zk__|*!FMcHwP!gwLJvS~9c0px8E zW%kxU@K!VDr=Sy-4^*jU-vz?hwr zgN>b&osEryn}d@J1b{3aZY~}W2V@9DD-$a-Gb`H|qMvW5}awt1(JSZA;@q>zSQc)8pmzcPOq?D?fx`w8fiK&^ng{76V zi>sTvho@I?NN8AiL}XNQN@`kqMrKxVNoiSmMP*fUOKV$uM`zch$y26In?7UatVN5L zEM2yI#mZHiHgDOwZTpU$yAB;ba`f2o6DLnyx_ss8wd*%--g@}x@sp>|p1*kc>f@)+ zU%r0({^RE_kiQrim?7Q*k`Rxf`AZP!FD6hNu!H=?$W#u*%z`YeiiT`Lj)Clng~Cck zjT|CQ6Blkg$f;}`^g%SK=pvVxipfLOk07sseMX$en#l4Q++zrT-D2QjW&}navmk># z!{3s>>*_Q4`Mn?T#=HFB{~d9B!H>me<{$mv6?NC-rS$g+SMcfg6;~KNK58d9>DlAB5Bm@O*n0D;_QJJyGB0j@ zy4f;T&t6O7N%6&$%8-dqAB6pF`Ny;WxWCko=?BWIrXSH~Kg`-Q-S9{MK|A$*7uVa^ zbG_QW+4)(bsQ+fox*t`mXL;T=m)NZ? tzOV1smP<9)Ugq9EdHi><@iwK&PrJi1y}aIf=C0Z{{c7~N-}?V=0su8URLlSX literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/icon-unknown.gif b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/icon-unknown.gif new file mode 100644 index 0000000000000000000000000000000000000000..d23ff27bfd7a0880f95196d808d6cb6542589600 GIT binary patch literal 376 zcmZ?wbhEHb6krfwxXJ(m|NsC0_wVoDzkmMx`ThI%uV24@{`~pl$B*xS|NQ>*``7PZ zKY#uF@$<*`AK$-y|MvCU*DqhceE$6DRWHJ$m%Ofdl*Z@87$3@18w-cJ11=W5c(jRZvinl9B>;GJ?HoN~*@wK%t>YhLxq2$-vW4k-tlpyO)#M(9=kC3Ll5u^j;PtPh&A9fvNI~XGj}+ znuxDjBfKt;)x^_OW$S7Yg`I4so@Nq4TLlFU$yb>fZeaR+b)) G4AuaCpUhYQ literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/image_document.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/image_document.png new file mode 100644 index 0000000000000000000000000000000000000000..134b6693687b2fa5fe36d48a9c0b8001f937c741 GIT binary patch literal 650 zcmV;50(Jd~P)VHAd+bMNh~)LLRqN>D)-jd9UvB%+hyKX5U|&4t0)fzgD-MPpQ$nHU%yoz=vI zMGb>1Xu!6Hw$NT~@Au<4P-+{9;Uw?&oj31uzH>xX0T7Xkz!(tn|Ed9-s_FqyReC13 z(ll)vW1O{Ck5ihay12Ob2ABc@RUI;zHpaMiyRDs0r>|D4rHw{ItJSJnYjt~jTbGuW z`X(~}?!&86q40R8<4zYw;$qi0^3ec=c&<&H;r`8W%H=Xymf^i;Wo6~<+}zx2UMzpC z*6MZN?(FMv`n|KO3(KFiUaucP0;Z!@LcUNa%8#vGK5aZ>wDgB0Gi=t*argWJcdlMQ z2#MpEX0wU+9&0U?N(F#OgpviU_Y{jYMsj65U3|PjwUOY}lUYj?MTiK_Il}NCVx-Eh zDx-TzMk7se+M#W_>?A1-x}ZXw3kkyz5kW)_hkjsi@RhKadN#H$Hq)$07*qoM6N<$f}lhwPXGV_ literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/invalid_name.gif b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/invalid_name.gif new file mode 100644 index 0000000000000000000000000000000000000000..fb7e0f34d6231868ed2f80b6067be837e70cac44 GIT binary patch literal 815 zcmZ?wbhEHbWMN=tXlGzx_z#4mU^E0qXb33&WMKq(T?a&f@&p4150I4La9D7liGhiU G!5RR1hX@}4 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/metadata.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/metadata.png new file mode 100644 index 0000000000000000000000000000000000000000..0c76bd1297751b66230f74719504b2adb02b1615 GIT binary patch literal 603 zcmV-h0;K(kP)^~*-1fljz_B$LUvK}k?BNXe#Y!m=zM!!V#}8bncK5m;8VP zw86G*RI63?Cd%b9bX|ueNlZ|wR6rj|r_)VIP@r2imh3?SN+^{|kY%~8B{maJ@F*OK z&VH9LwOeGt#DRjj0~v~8`>iO7!Ybi;zE$va`A^T#yW`y44;k^#O~K5*jD=qcUhPSc zvyy~q;5H_1WT1l~cqje9yfa+l!hu6xjdOJ8s;8E^+=QQ$tw p?%p!Hy#YapB=@+^9(46X{{RQg%9y;OKjr`c002ovPDHLkV1g7l326WT literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerAppResources.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerAppResources.java new file mode 100644 index 0000000..67dd8de --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerAppResources.java @@ -0,0 +1,52 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.resources.newres; + +import com.github.gwtbootstrap.client.ui.constants.BaseIconType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.user.client.ui.AbstractImagePrototype; + +/** + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * + */ +public class WorkspaceExplorerAppResources { + + public static final WorkspaceExplorerIcons ICONS = GWT.create(WorkspaceExplorerIcons.class); + /** Inject the icon's css once at first usage */ + static { + WorkspaceExplorerIcons icons = GWT.create(WorkspaceExplorerIcons.class); + icons.css().ensureInjected(); + } + + public static AbstractImagePrototype getIconCancel() { + + return AbstractImagePrototype.create(ICONS.cancel()); + } + + public static AbstractImagePrototype getIconLoading() { + + return AbstractImagePrototype.create(ICONS.loading()); + } + + public static AbstractImagePrototype getIconInfo() { + + return AbstractImagePrototype.create(ICONS.info()); + } + + /** My custom base icon collection */ + public enum CustomIconType implements BaseIconType { + + home, // Our runtime access + vre_folder, + new_folder; + + private static final String PREFIX = "myBaseIcon_"; + private String className; + + private CustomIconType() { + this.className = this.name().toLowerCase(); + } + @Override public String get() { + return PREFIX + className; + } + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerIcons.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerIcons.java new file mode 100644 index 0000000..34faf81 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/WorkspaceExplorerIcons.java @@ -0,0 +1,41 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.resources.newres; + +import com.google.gwt.resources.client.ClientBundle; +import com.google.gwt.resources.client.CssResource; +import com.google.gwt.resources.client.ImageResource; + +public interface WorkspaceExplorerIcons extends ClientBundle { + + /** Get access to the css resource during gwt compilation */ + @Source("baseIcons.css") + CssResource css(); + + @Source("cancel.png") + ImageResource cancel(); + + /** + * @return + */ + @Source("loading.gif") + ImageResource loading(); + + /** + * Our sample image icon. Makes the image resource for the gwt-compiler's + * css composer accessible + */ + @Source("loading.gif") + ImageResource logo(); + + @Source("vre_folder.png") + ImageResource vre_folder(); + + @Source("new_folder.png") + ImageResource new_folder(); + + @Source("home.png") + ImageResource home(); + + @Source("info-icon.png") + ImageResource info(); +} + diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/baseIcons.css b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/baseIcons.css new file mode 100644 index 0000000..c21077a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/baseIcons.css @@ -0,0 +1,32 @@ +/* Prevent our icons from css obfuscation */ +@external .myBaseIcon_*; /* Do some css stuff */ +.myBaseIcon_home:hover { + /* opacity: 0.5; */ + +} + +/* Our sample icon */ +@sprite .myBaseIcon_home { + gwt-image: "home"; + display: inline-block; + vertical-align: middle; + margin-bottom: 3px; + margin-right: 2px; +} + +/* Our sample icon */ +@sprite .myBaseIcon_vre_folder { + gwt-image: "vre_folder"; + display: inline-block; + vertical-align: middle; + margin-bottom: 3px; + margin-right: 2px; +} + +@sprite .myBaseIcon_new_folder { + gwt-image: "new_folder"; + display: inline-block; + vertical-align: middle; + margin-bottom: 3px; + margin-right: 2px; +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/cancel.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/cancel.png new file mode 100644 index 0000000000000000000000000000000000000000..9aa895bbf38f2303b1039c96f84b204a74281936 GIT binary patch literal 908 zcmV;719SX|P)F7{~vo_uSiCN+Y%uS|>6jKEz1I0J_tJB>NecODCrDtb3ma?D3-L7LZRTjr}v)Sl0bZ!&$siO=l{!j z{^xlJ9uo}(1-VPh%8IRSw;1m0yS?}P`TqZ_BM&EzQo4Dm$J3DaLUp<1auXs+(2_~q z4Fm>*EzO5I5|f9I0PGRKc7WEnT}Pg(t9w^mXeY|QF-(WU;EX}cc0kI>g{~+VZg0PK zJs5m>A4l{7z%i$zadrJ$yEIin@Z8z%-oAkYy})lOpe_Se6+0bY6uweZN<kq9x4&0jsd_qvMY3Fu7wPup86DOK~o|vpZWeDfs`yKX8B`bra( zoShB7zoUXw07dVVKhsMoMeCI=&q<&&E&gi#^WMtEPM-io8eG8i37?%-#&c9RFzCWAxtnwm@FmQB=^Hrx3HzFs=(Mdb)q4+6UZR z37G0ELQ><9|53E}NePg#%}V2TjZ42XeeXTagRf?azGVq!wipimY7=9=1grYd5T{?Z z!T6DlR(d0C($!?DYSzRLY}CJEGF3U2B}JBSZeKpZ%nOa1%L~NV596%*63{*8%kB)} zyOpZ`#vO~0Xq!yAX94SgjkOEJGr7|mu`?YGBYQ1NihUnft2^%#*NUdyUfFa=Wt?2% ze1D6ge>y)%TP;G<7DDQs(M@opk< iJFcpK8rze4xb{EOv{#A~ISFF`0000WFkZsqLGJ(ht=89 z#hsI#D}v$wf42WH6aW2ZU}9nV#5iO9nKi1?qQPv;j10_75X=NJ2#guQ=J2unXJBLa zhs|MM7}e^}{sJ;s@j0KHor%F-mYqRQmS6^RWKR>^?xVWgOsOaeEl$4a@p;*x1;> zz(5}#pYZVTkdTnX#KfSWps=v8fPjFAh=|b8(4?fK`1p8#fB(qH$l&1MgoK2cn3(_n z{{zhqo-{`kNXeE2`2_<-Z~}(Nw&z(ug)2Q>978H@+4M#79Z}$Mj$QDYA+_D%ef>F4 z_shSOz2@m0-;ot=%bk6B)0x-X9IvmsqNiaTIn&{FK()A%@KTfW(sM35YMHw2vpwDQ zB8H=MgHhzS14mwbk00^R8{ivXh_l-Yq!A;^SrcV|r(!wRg<{!#TxLdJ?OSu$tX{@_gm>@CHVP4SqtC U*M`r#0dzEjr>mdKI;Vst08CJ>g#Z8m literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/info-icon.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/info-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ad1e0965e840f6cdb893b3cfad78614f252a17ff GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!73?$#)eFPFP2=EDU{r~?z1Iq&9QHR~v7?43F zL4LsuOk%3qPN8}Eg%!1Rvz9FXc7EMMpj?Wli(^Pdob5SV-sS{}){D-Q|M9hKJw2U^ zk#&iu>H`Lq5GIQQ+!hO%x)_h0ll8dw*5~_9jqSNjzn7nw$9$9j)}gJ9!RsI0**L?} zX2n{Wc$N4(<;nxQlxLP-(bCJGCeh>K^7xp1&TXmwvwL|wfc7zXy85}Sb4q9e0I392 As{jB1 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/info.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/info.png new file mode 100644 index 0000000000000000000000000000000000000000..145ed1d53c0154c2d508586dd57ae63dd6e120b1 GIT binary patch literal 260 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`r#)R9Ln>}1ryO8ObC|<)WRb%k zX{}>iN7gr1@CnR!3Omzrco{O|IFHCW z)J$Qt-@x{WOM#DFlF2y1Oh8}3$#|0@r^B369AAx3Y)R7L@?KbCF19mn!fHphGfa=v zbn4oE&Svb7kv-Ay)j_7?@XEM=Drvr-Ulo|c7z-u%Sic7B5^VpYwMwGlJa-FEgujNs zM@a^Lmzs+ad`qo2o;bKzkVV7GL&2dis7=zTEX|2cB{iMFA>1N)*0Rf@KyNX4y85}S Ib4q9e00*vG{r~^~ literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/loading.gif b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/newres/loading.gif new file mode 100644 index 0000000000000000000000000000000000000000..e147426f23b581693164b7cdf22fd5f99b15c0ed GIT binary patch literal 8114 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 N22WQ%mvv4FO#o7>8+iZ# literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/pdf_document.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/pdf_document.png new file mode 100644 index 0000000000000000000000000000000000000000..8f8095e46fa4965700afe1f9d065d8a37b101676 GIT binary patch literal 591 zcmV-V0~O9lw>B8WRlD)Gm}Jrz31u-X&&gn2lvjs=i{7nIaL6v2==uw+8Lcs(8j27 z;|c`rmSv@Lx!heopGP^^Ieb3f=R!%Lpp$}iMS-&P3EJ)s48wrJ_Ni0~k|c47D2nj= z{jS6bt|kFpFf|p5cM`_&0Zh|`rfEp0(}=}lT#(6RpzAsUfxv^LSYX>WlAaN$>)*J5 z0#sE+JRUD8iT9*fz{)_^7@6P&!sEjTcD+I9Z4YjT1`wH@fV{cEvneYGFU%maIEU2s55&K(LixD|{p-uiS@?KNj zk-Go8G$hH6g002ovPDHLkV1hVj1#|!a literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/query.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/query.png new file mode 100644 index 0000000000000000000000000000000000000000..d9eefc22513d4e100b3eea40d529bdc600913f88 GIT binary patch literal 775 zcmV+i1Ni)jP)5nA-%a4+}V@4MeQ=X-`y3jgzYw>wNE z5*85;QH)9{yJ+p8psh^O`jOT<6p7*CVPX8KfWSR;_8=4r^@hV?1cN~Y0s-iIg+c*q zYin3oSU@(LeL-jE{vwFSxdb>guXioAv$#n*<*5Hy`WXQQPW*6cdmY2Ttw-e0$D< zqaN8z#w|mGW3d>h51UPtLPm+;LQQZlc;O8^zCL=zMme9t5H5`|cvg>BpLcs$jf zxCG0uPt=msOa7)qbpR=MGBleFu}53-T&&w)_lJ{Jx~u`zUtWTQOqxag+{>}`{DQbNeQdIy48b9rSiL# zC6`Zp{;*Nvjc6UXh2@nJxZ_mw+E|fD1lnZjbb3?4R`T=Xp3_u9+hV@?dRh&Pb$`hO z^{g$+a)J7F4c1oHE}WT}$&jIjs!sg$u&Y-IA=}T-C#R>U_mRYF6eHB}20eG}zFaPc za=EO5_o^v(O5NtVlYM%#Ro%7eBuxI;@>bnnD}I(i4wn}iBU8dG$ABV6f`YrDV9R{ zD239}kL~Wxc!z=#o=n{2WM=NpIdjk4JA^R?|MQ85Z%-B`k_4hCf?zO|6GFTgI*DjO z6eE5h2Jx_Gl+vidVCcrR_rncmkGM^+UKH5Xx+?R*YNxruS}fLM%$iDT4Kqtw?_?x% znKCx0Yg)%9LHI*utkNhlZ|6~mtIlb*8VNC}c?uj7A(mRZxw@mpeo8}fS6iiwVwqa63DX<%O9fl$4o3Q0zA!1-VG)ga zMP=V2i8)m7LxE8(li}HQBU-PW--{>bKr#y4F61`__z4(L%_bqHX>=((9Z%_0A1zoD zK$0XcFZKPWOWl+=FFX_l*1G)82ih5|-*szd!sp z0|5Elg%&xJE8J`adVKz5$cKbaSa;xiB%|?=tIBpJo}+6tpPg3~CAu!4Zg`nj2*gqh zYV1YO`*47#H-zK|I$FU7>%s@k0Wgy7S?#d&) zlOdVa*z7E0A(uq}-=kMaHIwsW%dZoO;Mfm_<2Oe(?(HoxnU2{Hc=kx{dK*e|W*Xbu)-8Wsm$HQ(N)Ek< zrc#vXMLdW}TWpphCZsGREkUZr{Mg;M&b;luZ0IGA9rnH1`DVU1->eh_0hG(-dw<@) z-1S-xc+D!@wd^?Z=a`M%%phe@J_EnT0QpH7V3 jcG~XA#&PRl)Zh6(yXt(^KFGF}00000NkvXXu0mjfDwr>g literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/report_template.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/report_template.png new file mode 100644 index 0000000000000000000000000000000000000000..b4aaad9a45c9abbee2d47611a6963101b64a8023 GIT binary patch literal 519 zcmV+i0{H!jP)l0tqi6&npJ$x10^Z5HznC|jkhtXU{*?AXX+vSK$&lqrKo z4P`-MYRWlh-uHXoo+plGVQMtjm29&SnPTept1G}>;1qBiY)nF?X%bBWNhny_l)Z3d z&-N3@T)lWSVVldhUf%V8y7}mh3o^f*rno=*oe{IP>4|aPep(t*WGZD`whRe#WKrpOeww^A5*|8>ZEI3iJG3d@;ddSaaQQiv*3SWXm^*Pk(vkYVP=SQ%7gX+6s4|5yBQ}3^T_6XQ zZDbP)D!Ze~6zXIkQ9PYpWTZE?jfD>%Y1@{Swk5itNez`{Q)G&e7J>b9cP_BngG&!t zi|rp2nJV;T^4jymwofAMkUFri0;>ZDmaq-jpk-+0DUxkA;uk8$FcGE_?o$8&002ov JPDHLkV1i%8-68-0 literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/root.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/root.png new file mode 100644 index 0000000000000000000000000000000000000000..fed62219f57cdfb854782dbadf5123c44d056bd4 GIT binary patch literal 806 zcmV+>1KIqEP)v;U&v3%|^C`Ga3?LtY&4dQB4Oz;1v;J%z!D&%WRH@BZ?x; z3)8@IUIv@hG|@IwyHLC`l{1<4BK>wam95g|i|?Cfzt876&-Zx_0f5*l-9`IJI&mHu zE6$@xB)6N}7VeR;!X8D!TAw;;&0Bsj?A071cO>X3K0wl7WZ1;Tg!4LHyNcnzoeQ7t zNW`aSlm8WXYkek&ir$13=ngczvf zV0vnjNpCF&K8px}dunv+`LIb-sOC$_jD(;IBI$xC|7`(+9cA>Vir_V#z{?k7SX^Ah z^71m~W@q439Ycqfhi7+gp#A14n1n1!e>$EdeATG|f798Y=ggzwEKH2Q!qU2QA(Se?dwqG69%>n$6rtE z%F(845Az8c{w(XgimJg96!jLMz?zS6I1HUm2baqQx7&@nx;lhHA!r6vs2|fqJETOu zLxeu2OQ(3(au%dg>AcZsWI(zXn9XJg1cLe8k~0h0wOL=&HK}7X k{AKr*U4z7Szv)i%9gTgghwgU$Q~&?~07*qoM6N<$g31kYk^lez literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/shared_folder.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/shared_folder.png new file mode 100644 index 0000000000000000000000000000000000000000..2cd28412b415b4491c3a15106b647feba5f572b6 GIT binary patch literal 887 zcmV--1Bm>IP)^ETwEew!5>tv%51pGoINkjSqU}-g!7T=XcKi-*ePp-?Qh!hTju~0kJ8= zM45U>DdS$eX)0wKqA95(Aq*<32~dv<2W`9 zqLV=wz9OJdw=$df+2cZ1SWCCjeW^7gS1-}%C(3F8D8GHY**&?MVo^l zyr`RHc~eB*Y@D9P)G4Veg<%NRPV(XYk9ndyMP^9{#S&b&I8Og}L+seOvA*u^MG_GM z!YYQNq-*%@YLt8}iiee z+SDX`&6h|qP{9m<_%ho4H@yZU5zx6Ey!NO~BqmTDK?d9sg zAjxEsa?xQjd!3KIdYAm=Gfd1@zt{5KIFsX~R&J1+OcT!iLhO?zVnWvH5p88TT9Ou|`hN`^j(pMtp_R%?Z-?u7&!DsP9T6l_*p__MhI(H{<(Qz4AVyz@=K6 zA(2RNY`BNla!2w{9nCswu=X6wo-qeJ}IgO@~#1kO_!wJLl`yqVX%%Ra(uAWBJy2MT(-nt z;)OK|w^Gr%>(JRP@AP(bd44vCn>>=%EIJi8*X{gtbt=vDw2Lpg?maf&`=X5&;D~Kg zskrE&FSq}(>A=r_&A0h23))xAa^cEimS*hM@Z36W&X?l+@Ep}j4JCkuC_{zZrae}j zdY|OYGjEu8J$h8SP5*oPnv52tp>hLnEB@cove(Ve@PAp1z4ng)0|55|Noj(bCItWh N002ovPDHLkV1oM`ug(Af literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/timeseries.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/timeseries.png new file mode 100644 index 0000000000000000000000000000000000000000..abcd93689a08ec9bdbf0984927e8da06c043c7cd GIT binary patch literal 566 zcmV-60?GY}P)>q?GuNnCdgP^*Bj5V_b?dAq2Ppn9^MBB^YUM zad0N-T{Ujg*A6d~mYV4na=hT4Nz+_}SGTgW|Iir!%$ z;@OGkWI6+j0H}~K4RYR%!7y|zM`O@*K>rL{*&}x3lR**HrMXC1->#slU>X|w!U1xQ zqcOOAS;jTeL{ZSdz-%)SMH9tDF;N4B6%j=d15J&5qy`F#vB?Ar zqS1nH@%ny_XSI*Y>) z1f5QYdmzT>YciP<3WehS<{GovEaLGv27>{*-7f0&I$yJ^L%ZGPv1YT$V|u;*+ZCWz ztHI~CDVsuy($SfR6-`N~K?9GTB#l%%0h7 z-q`K-y~E)+s8lMyTrPL8^_pUo)9G|SluG5pPqw6!LJB_PzyJUM07*qoM6N<$f^=yZ AYybcN literal 0 HcmV?d00001 diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/workflow_report.png b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/resources/workflow_report.png new file mode 100644 index 0000000000000000000000000000000000000000..f35a97938cc4fb08f06ebd7f8571526338ef5377 GIT binary patch literal 756 zcmVLMJ44Z(P$%#Ob!q#T1>~_OL|8>GWv|h92aa9 z{ih?;wSVF8wbi6u7gt=;%4KDEJzG}p;qAaH;=^%nG(BPMqDp@klu}ijdLQ=94+Sv> z5{U%ocC@0D%Irbp!4@n#NPHkpOYK#D^dF_A89qTKGV%LqLqA&{k|D2>yV7qLmg~*x1@cbjz3zP!z2FhV16<-TNNz zuIz$fLNt0{xWmll%$dUkM1*+|PHJ2ZGvdmC35A3UoF6R(-~DS$BH+@Xy#VYsLyQ>z zxq>v8$ny|FSR~0W2u4ic`k5mcbEIiLksz4Y#KyE{9LLn}_oq&%6$}Oga?Zh83$3-^ zU4V1$eaMkz85m>bTh*c{3ch%tltQ=L4Q7$u>-Ff*JP6K)r(~Ul_41v6uR1rSij#*! zl14&E?hS3Iagod#Oo#p}d7WbijUO{Mqc5?@<$>unxw*22 z?bQuGkPsSMOgEm)qR1=cLLyZOm>T65_V?)|o0p=i_uUiST44Cz-W mqJp!8r`H!$*8T4x&4Leh&Epbde3h>N0000 getBreadcrumbsByItemIdentifier(String itemIdentifier, + boolean includeItemAsParent) throws Exception; + + /** + * Check name. + * + * @param name the name + * @return true, if successful + * @throws WorkspaceNavigatorServiceException the workspace navigator service exception + */ + boolean checkName(String name) throws WorkspaceNavigatorServiceException; + + Item getFolder( + Item folder, List showableTypes, boolean purgeEmpyFolders, + FilterCriteria filterCriteria) throws WorkspaceNavigatorServiceException; + + /** + * Gets the root. + * + * @param showableTypes the showable types + * @param purgeEmpyFolders the purge empy folders + * @param filterCriteria the filter criteria + * @return the root + * @throws WorkspaceNavigatorServiceException the workspace navigator service exception + */ + Item getRoot(List showableTypes, boolean purgeEmpyFolders, + FilterCriteria filterCriteria) + throws WorkspaceNavigatorServiceException; + + /** + * Gets the my special folder. + * + * @param showableTypes the showable types + * @param purgeEmpyFolders the purge empy folders + * @param filterCriteria the filter criteria + * @return the my special folder + * @throws WorkspaceNavigatorServiceException the workspace navigator service exception + */ + Item getMySpecialFolder(List showableTypes, + boolean purgeEmpyFolders, FilterCriteria filterCriteria) + throws WorkspaceNavigatorServiceException; + + /** + * Gets the item by category. + * + * @param category the category + * @return the item by category + * @throws WorkspaceNavigatorServiceException the workspace navigator service exception + */ + Item getItemByCategory(ItemCategory category)throws WorkspaceNavigatorServiceException; + + /** + * Gets the size by item id. + * + * @param itemId the item id + * @return the size by item id + * @throws Exception the exception + */ + Long getSizeByItemId(String itemId) throws Exception; + + /** + * Gets the mime type. + * + * @param itemId the item id + * @return the mime type + * @throws Exception the exception + */ + String getMimeType(String itemId) throws Exception; + + /** + * Gets the user acl for folder id. + * + * @param folderId the folder id + * @return the user acl for folder id + * @throws Exception the exception + */ + String getUserACLForFolderId(String folderId) throws Exception; + + + /** + * Gets the readable size by item id. + * + * @param id the id + * @return the readable size by item id + * @throws Exception the exception + */ + String getReadableSizeByItemId(String id) throws Exception; + + /** + * @param itemIdentifier + * @param parentLimit + * @param includeItemAsParent + * @return + * @throws Exception + */ + List getBreadcrumbsByItemIdentifierToParentLimit( + String itemIdentifier, String parentLimit, + boolean includeItemAsParent) throws Exception; + + /** + * @param nameFolder + * @param description + * @param parentId + * @param showableTypes + * @param filterCriteria + * @return + * @throws Exception + */ + Item createFolder( + String nameFolder, String description, String parentId) + throws Exception; + + /** + * @param itemId + * @return + * @throws Exception + */ + String getPublicLinkForItemId(String itemId) + throws Exception; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/rpc/WorkspaceExplorerAppServiceAsync.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/rpc/WorkspaceExplorerAppServiceAsync.java new file mode 100644 index 0000000..a9a10de --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/rpc/WorkspaceExplorerAppServiceAsync.java @@ -0,0 +1,169 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.rpc; + +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.FilterCriteria; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemCategory; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; + +import com.google.gwt.user.client.rpc.AsyncCallback; + + +/** + * The Interface WorkspaceExplorerServiceAsync. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 24, 2015 + */ +public interface WorkspaceExplorerAppServiceAsync { + + /** + * Gets the root. + * + * @param showableTypes + * the showable types + * @param purgeEmpyFolders + * the purge empy folders + * @param filterCriteria + * the filter criteria + * @param callback + * the callback + * @return the root + */ + public void getRoot(List showableTypes, boolean purgeEmpyFolders, + FilterCriteria filterCriteria, AsyncCallback callback); + + /** + * Check name. + * + * @param name + * the name + * @param callback + * the callback + */ + public void checkName(String name, AsyncCallback callback); + + + /** + * Gets the folder. + * + * @param folder the folder + * @param showableTypes the showable types + * @param purgeEmpyFolders the purge empy folders + * @param filterCriteria the filter criteria + * @param callback the callback + * @return the folder + */ + public void getFolder(Item folder, List showableTypes, + boolean purgeEmpyFolders, FilterCriteria filterCriteria, + AsyncCallback callback); + + + /** + * Gets the breadcrumbs by item identifier. + * + * @param itemIdentifier the item identifier + * @param includeItemAsParent the include item as parent + * @param asyncCallback the async callback + * @return the breadcrumbs by item identifier + */ + public void getBreadcrumbsByItemIdentifier(String itemIdentifier, + boolean includeItemAsParent, AsyncCallback> asyncCallback); + + /** + * Gets the my special folder. + * + * @param showableTypes the showable types + * @param purgeEmpyFolders the purge empy folders + * @param filterCriteria the filter criteria + * @param asyncCallback the async callback + * @return the my special folder + */ + public void getMySpecialFolder(List showableTypes, boolean purgeEmpyFolders, FilterCriteria filterCriteria, AsyncCallback asyncCallback); + + /** + * Gets the item by category. + * + * @param category the category + * @param asyncCallback the async callback + * @return the item by category + */ + public void getItemByCategory(ItemCategory category, AsyncCallback asyncCallback); + + /** + * Gets the size by item id. + * + * @param id the id + * @param asyncCallback the async callback + * @return the size by item id + */ + public void getSizeByItemId(String id, AsyncCallback asyncCallback); + + + /** + * Gets the readable size by item id. + * + * @param id the id + * @param asyncCallback the async callback + * @return the readable size by item id + */ + public void getReadableSizeByItemId(String id, AsyncCallback asyncCallback); + + /** + * Gets the mime type. + * + * @param id the id + * @param asyncCallback the async callback + * @return the mime type + */ + public void getMimeType(String id, AsyncCallback asyncCallback); + + /** + * Gets the user acl for folder id. + * + * @param id the id + * @param asyncCallback the async callback + * @return the user acl for folder id + */ + public void getUserACLForFolderId(String id, + AsyncCallback asyncCallback); + + /** + * Gets the breadcrumbs by item identifier to parent limit. + * + * @param itemIdentifier the item identifier + * @param parentLimit the parent limit + * @param includeItemAsParent the include item as parent + * @param callback the callback + * @return the breadcrumbs by item identifier to parent limit + */ + void getBreadcrumbsByItemIdentifierToParentLimit(String itemIdentifier, + String parentLimit, boolean includeItemAsParent, + AsyncCallback> callback); + + /** + * Creates the folder. + * + * @param nameFolder the name folder + * @param description the description + * @param parentId the parent id + * @param callback the callback + */ + void createFolder( + String nameFolder, String description, String parentId, + AsyncCallback callback); + + /** + * Gets the public link for item id. + * + * @param itemId the item id + * @param callback the callback + * @return the public link for item id + */ + void getPublicLinkForItemId(String itemId, AsyncCallback callback); + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.java new file mode 100644 index 0000000..5519abc --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.java @@ -0,0 +1,171 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.view; + +import java.util.LinkedHashMap; +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.client.event.BreadcrumbClickEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.BreadcrumbInitEvent; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +import com.github.gwtbootstrap.client.ui.NavLink; +import com.google.gwt.core.client.GWT; +import com.google.gwt.event.dom.client.ClickEvent; +import com.google.gwt.event.dom.client.ClickHandler; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; + +/** + * The Class Breadcrumbs. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jun 23, 2015 + */ +public class Breadcrumbs extends Composite { + + public static final String DIVIDER = "/"; + private LinkedHashMap hashListItems = new LinkedHashMap();// Ordered-HashMap + private Item lastParent; + private static BreadcrumbsUiBinder uiBinder = GWT.create(BreadcrumbsUiBinder.class); + + @UiField + com.github.gwtbootstrap.client.ui.Breadcrumbs breadcrumbs; + + private HandlerManager eventBus; + + /** + * The Interface BreadcrumbsUiBinder. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it Jun 23, + * 2015 + */ + interface BreadcrumbsUiBinder extends UiBinder { + } + + /** + * Instantiates a new breadcrumbs. + */ + public Breadcrumbs(HandlerManager eventBus) { + initWidget(uiBinder.createAndBindUi(this)); + this.getElement().setId("breadcrumbs_we"); + this.getElement().setAttribute("id", "breadcrumbs_we"); + this.setStyleName("breadcrumbs-we"); + this.eventBus = eventBus; + breadcrumbs.setDivider(DIVIDER); +// init(); + // initBreadcrumb(true); + + } + + /** + * Sets the path. + * + * @param parents + * the new path + */ + public void setPath(List parents) { + resetBreadcrumbs(); + if (parents != null && parents.size() > 0) { + for (Item parent : parents) { + GWT.log("parent is: "+parent); + addNavigationLink(parent); + hashListItems.put(parent.getId(), parent); + } + lastParent = parents.get(parents.size() - 1); + } + } + + /** + * Checks if is root or special folder. + * + * @param item the item + * @return true, if is root or special folder + */ + private boolean isRootOrSpecialFolder(Item item){ + GWT.log(item.getName() +" is root "+(item.getParent()==null)); + GWT.log(item.getName() +" is special folder "+item.isSpecialFolder()); + return item.getParent()==null || item.isSpecialFolder(); + } + + /** + * Reset breadcrumbs. + */ + private void resetBreadcrumbs() { + breadcrumbs.clear(); + hashListItems.clear(); + } + + // @UiHandler("add") + + /** + * Adds the navigation link. + * + * @param parent the parent + */ + private void addNavigationLink(Item parent) { + if(parent==null) + return; + + final NavLink navLink = new NavLink(parent.getName()); + navLink.setName(parent.getId()); + breadcrumbs.add(navLink); + navLink.addClickHandler(new ClickHandler() { + + @Override + public void onClick(ClickEvent event) { + + Item target = hashListItems.get(navLink.getName()); +// WorkspaceExplorerController.eventBus.fireEvent(new LoadFolderEvent(target)); + eventBus.fireEvent(new BreadcrumbClickEvent(target)); + } + }); + } + + /** + * Breadcrumb is empty. + * + * @return true, if successful + */ + public boolean breadcrumbIsEmpty() { + + if (hashListItems.size() == 0) + return true; + + return false; + } + + /** + * Gets the last parent. + * + * @return the last parent + */ + public Item getLastParent() { + return lastParent; + } + + + /** + * Inits the. + * + * @param item the item + */ + public void init(Item item) { + resetBreadcrumbs(); + addNavigationLink(item); + hashListItems.put(item.getId(), item); + lastParent = item; + eventBus.fireEvent(new BreadcrumbInitEvent(item)); + } + + + /** + * Clear. + */ + public void clear() { + resetBreadcrumbs(); + } +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.ui.xml b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.ui.xml new file mode 100644 index 0000000..b86cb48 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/Breadcrumbs.ui.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/PopupContextMenu.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/PopupContextMenu.java new file mode 100644 index 0000000..db52470 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/PopupContextMenu.java @@ -0,0 +1,63 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.view; + +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.MenuMoreOptionsOnItem; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemInterface; + +import com.google.gwt.core.shared.GWT; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.client.Command; +import com.google.gwt.user.client.ui.PopupPanel; + + +/** + * The Class PopupContextMenu. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 11, 2016 + */ +public class PopupContextMenu extends PopupPanel{ + + + private MenuMoreOptionsOnItem menuOpts; + + /** + * Instantiates a new popup context menu. + * + * @param autohide the autohide + * @param eventBus the event bus + * @param itemToDownload the item to download + */ + public PopupContextMenu(boolean autohide, HandlerManager eventBus, ItemInterface itemToDownload) { + super(autohide); + GWT.log("PopupContextMenu opened"); + menuOpts = new MenuMoreOptionsOnItem(eventBus); + setWidth("100px"); + addStyleName("context-menu-we"); + + Command cmd = new Command() { + + @Override + public void execute() { + hide(); + } + }; + + menuOpts.initOnItem(itemToDownload, cmd); + add(menuOpts); + } + + /** + * Show popup at x,y position + * + * @param x the x + * @param y the y + */ + public void showPopup(int x, int y){ + + setPopupPosition(x, y); + show(); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectableTypes.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectableTypes.java new file mode 100644 index 0000000..b95fd12 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectableTypes.java @@ -0,0 +1,34 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.view; + +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; + +/** + * The Interface SelectableTypes. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 29, 2015 + */ +public interface SelectableTypes { + + + /** + * Sets the selectable types. + * + * @param selectableTypes the new selectable types + */ + public void setSelectableTypes(ItemType ... selectableTypes); + + + /** + * Gets the selectable types. + * + * @return the selectable types + */ + public List getSelectableTypes(); + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectionItem.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectionItem.java new file mode 100644 index 0000000..acfb70c --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/SelectionItem.java @@ -0,0 +1,26 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.view; + +import java.util.Set; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + +/** + * The Interface SelectionItem. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 29, 2015 + */ +public interface SelectionItem { + + + /** + * Gets the selected items. + * + * @return the selected items + */ + Set getSelectedItems(); + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/ShowableTypes.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/ShowableTypes.java new file mode 100644 index 0000000..0b49da2 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/ShowableTypes.java @@ -0,0 +1,33 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.client.view; + +import java.util.List; + +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; + + +/** + * The Interface ShowableTypes. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 29, 2015 + */ +public interface ShowableTypes { + + + /** + * Gets the showable types. + * + * @return the showable types + */ + public List getShowableTypes(); + + /** + * Sets the showable types. + * + * @param showableTypes the new showable types + */ + public void setShowableTypes(ItemType ... showableTypes); +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/WorkspaceExplorer.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/WorkspaceExplorer.java new file mode 100644 index 0000000..b311c33 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/client/view/WorkspaceExplorer.java @@ -0,0 +1,361 @@ +package org.gcube.portlets.user.workspaceexplorerapp.client.view; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Set; + +import org.gcube.portlets.user.workspaceexplorerapp.client.Util; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerApp; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerAppConstants; +import org.gcube.portlets.user.workspaceexplorerapp.client.event.RootLoadedEvent; +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.DisplayField; +import org.gcube.portlets.user.workspaceexplorerapp.client.grid.ItemsTable; +import org.gcube.portlets.user.workspaceexplorerapp.client.resources.newres.WorkspaceExplorerAppResources; +import org.gcube.portlets.user.workspaceexplorerapp.shared.FilterCriteria; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; + +import com.github.gwtbootstrap.client.ui.Alert; +import com.github.gwtbootstrap.client.ui.constants.AlertType; +import com.google.gwt.core.client.GWT; +import com.google.gwt.dom.client.Style.Unit; +import com.google.gwt.event.shared.HandlerManager; +import com.google.gwt.user.client.Window; +import com.google.gwt.user.client.rpc.AsyncCallback; +import com.google.gwt.user.client.ui.HTML; +import com.google.gwt.user.client.ui.HorizontalPanel; +import com.google.gwt.user.client.ui.Image; +import com.google.gwt.user.client.ui.ScrollPanel; + + +/** + * The Class WorkspaceExplorer. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Aug 4, 2015 + */ +public class WorkspaceExplorer implements ShowableTypes, SelectableTypes{ + + + protected static final HorizontalPanel LOADING_PANEL = new HorizontalPanel(); + protected static final Image LOADING_IMAGE = WorkspaceExplorerAppResources.getIconLoading().createImage(); + + static { + LOADING_PANEL.setWidth("95%"); + LOADING_PANEL.getElement().getStyle().setPadding(5.0, Unit.PX); +// LOADING_PANEL.setSpacing(3); + LOADING_PANEL.add(LOADING_IMAGE); + HTML loading = new HTML("Loading..."); + loading.getElement().getStyle().setPaddingLeft(5.0, Unit.PX); + LOADING_PANEL.add(loading); + } + + protected Alert alert = new Alert(); + protected List selectableTypes = new ArrayList(); + protected List showableTypes = new ArrayList(); + protected FilterCriteria filterCriteria = null; + protected boolean showEmptyFolders = true; + protected ScrollPanel explorerPanel; + private ItemsTable itTables; + private DisplayField[] displayFields; + private HandlerManager eventBus; + + + /** + * Instantiates a new workspace explorer. + * + * @param eventBus the event bus + * @param showableTypes the showable types + * @param selectableTypes the selectable types + * @param fields the fields + */ + public WorkspaceExplorer(HandlerManager eventBus, ItemType[] showableTypes, ItemType[] selectableTypes, DisplayField...fields) { + this.eventBus = eventBus; + setShowableTypes(showableTypes); + setSelectableTypes(selectableTypes); + itTables = new ItemsTable(eventBus, true, fields); + explorerPanel = new ScrollPanel(); + explorerPanel.getElement().setId("explorer_panel_we"); + explorerPanel.getElement().setPropertyString("id", "explorer_panel_we"); + } + + + /** + * Instantiates a new workspace explorer. + * + * @param eventBus the event bus + * @param filterCriteria the filter criteria + * @param showableTypes the showable types + * @param selectableTypes the selectable types + * @param fields the fields + */ + public WorkspaceExplorer(HandlerManager eventBus, FilterCriteria filterCriteria, ItemType[] showableTypes, ItemType[] selectableTypes, DisplayField...fields) { + this(eventBus, showableTypes, selectableTypes, fields); + this.filterCriteria = filterCriteria; + } + + /** + * Sets the alert. + * + * @param html the html + * @param type the type + */ + public void setAlert(String html, AlertType type){ + explorerPanel.clear(); + alert.setHTML(html); + alert.setType(type); + alert.setClose(false); + explorerPanel.add(alert); + } + + /** + * Set the panel in loading mode. + */ + protected void setLoading() { + explorerPanel.clear(); + explorerPanel.add(LOADING_PANEL); + } + + /** + * Load the Workspace Tree. + */ + public void loadRoot() { + GWT.log("loading tree data"); + setLoading(); + + // we make a copy of showable types + List showableTypesParam = new ArrayList(showableTypes); + + // we get sure that folders are displayed + for (ItemType folder : Util.FOLDERS) { + if (!showableTypesParam.contains(folder)) + showableTypesParam.add(folder); + } + + boolean purgeEmpyFolders = !showEmptyFolders; + + GWT.log("loading workspace tree from server"); + + WorkspaceExplorerAppConstants.workspaceNavigatorService.getRoot(showableTypesParam, purgeEmpyFolders, filterCriteria, new AsyncCallback() { + + public void onFailure(Throwable caught) { + Window.alert(caught.getMessage()); + setAlert(caught.getMessage(), AlertType.ERROR); + GWT.log("Error loading workspace tree from server",caught); + } + + public void onSuccess(Item item) { + eventBus.fireEvent(new RootLoadedEvent(item)); + updateExplorer(item.getChildren()); + } + + }); + } + + /** + * Load folder. + * + * @param item the item + * @throws Exception the exception + */ + public void loadFolder(final Item item) throws Exception { + GWT.log("loading folder data"); + setLoading(); + + if(!item.isFolder()) + throw new Exception("Item is not a folder"); + + if(item.getId()==null || item.getId().isEmpty()) + throw new Exception("Item id is null or empty"); + + // we make a copy of showable types + List showableTypesParam = new ArrayList(showableTypes); + + // we get sure that folders are displayed + for (ItemType folder : Util.FOLDERS) { + if (!showableTypesParam.contains(folder)) + showableTypesParam.add(folder); + } + + boolean purgeEmpyFolders = !showEmptyFolders; +// FilterCriteria filterCriteria = new FilterCriteria(allowedMimeTypes,requiredProperties, allowedFileExtensions); + + GWT.log("loading workspace folder by item id from server: "+item.getId()); + WorkspaceExplorerAppConstants.workspaceNavigatorService.getFolder(item, showableTypesParam, purgeEmpyFolders, filterCriteria, new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Window.alert(caught.getMessage()); + setAlert(caught.getMessage(), AlertType.ERROR); + GWT.log("Error loading workspace folder from server",caught); + } + + @Override + public void onSuccess(Item result) { + if(item.getName()==null || item.getName().isEmpty()) + item.setName(result.getName()); + + updateExplorer(result.getChildren()); + } + }); + } + + /** + * Load the Workspace Tree. + */ + public void loadMySpecialFolder() { + GWT.log("loading folder data"); + setLoading(); + + + // we make a copy of showable types + List showableTypesParam = new ArrayList(showableTypes); + + // we get sure that folders are displayed + for (ItemType folder : Util.FOLDERS) { + if (!showableTypesParam.contains(folder)) + showableTypesParam.add(folder); + } + + boolean purgeEmpyFolders = !showEmptyFolders; +// FilterCriteria filterCriteria = new FilterCriteria(allowedMimeTypes,requiredProperties, allowedFileExtensions); + + GWT.log("loading workspace tree from server"); + WorkspaceExplorerAppConstants.workspaceNavigatorService.getMySpecialFolder(showableTypesParam, purgeEmpyFolders, filterCriteria, new AsyncCallback() { + + @Override + public void onFailure(Throwable caught) { + Window.alert(caught.getMessage()); + setAlert(caught.getMessage(), AlertType.ERROR); + GWT.log("Error loading workspace folder from server",caught); + } + + @Override + public void onSuccess(Item items) { + updateExplorer(items.getChildren()); + } + }); + } + + /** + * Update explorer. + * + * @param items the items + */ + public void updateExplorer(ArrayList items){ + GWT.log("workspace explorer updating.."); + explorerPanel.clear(); +// itTables = new ItemsTable(true, displayFields); + itTables.updateItems(items, true); + explorerPanel.add(itTables.getCellTable()); + GWT.log("workspace explorer updated"); + WorkspaceExplorerApp.updateSize(); + } + + + /** + * Adds the item to explorer. + * + * @param item the item + */ + public void addItemToExplorer(Item item){ + GWT.log("workspace explorer add item.."+item); +// itTables = new ItemsTable(true, displayFields); +// explorerPanel.clear(); + itTables.addItems(Arrays.asList(item)); +// explorerPanel.add(itTables.getCellTable()); + GWT.log("added item: "+item.getName() +", to Explorer"); + } + + /** + * Gets the panel. + * + * @return the explorerPanel + */ + public ScrollPanel getPanel() { + return explorerPanel; + } + + + /** + * Gets the display fields. + * + * @return the displayFields + */ + public DisplayField[] getDisplayFields() { + return displayFields; + } + + + /** + * Sets the display fields. + * + * @param displayFields the displayFields to set + */ + public void setDisplayFields(DisplayField[] displayFields) { + this.displayFields = displayFields; + itTables.setDisplayFields(displayFields); + } + + + /** + * Gets the it tables. + * + * @return the itTables + */ + public ItemsTable getItTables() { + return itTables; + } + + /** + * Gets the items selected. + * + * @return the items selected + */ + public Set getItemsSelected(){ + return itTables.getSelectedItems(); + } + + /** + * Gets the selectable types. + * + * @return the selectableTypes + */ + @Override + public List getSelectableTypes() { + return selectableTypes; + } + + /** + * Sets the selectable types. + * + * @param selectableTypes the selectableTypes to set + */ + @Override + public void setSelectableTypes(ItemType ... selectableTypes) { + this.selectableTypes.clear(); + if (selectableTypes!=null) for (ItemType type:selectableTypes) this.selectableTypes.add(type); + } + + /** + * Gets the showable types. + * + * @return the showableTypes + */ + @Override + public List getShowableTypes() { + return showableTypes; + } + + /** + * Sets the showable types. + * + * @param showableTypes the showableTypes to set + */ + @Override + public void setShowableTypes(ItemType ... showableTypes) { + this.showableTypes.clear(); + if (showableTypes!=null) for (ItemType type:showableTypes) this.showableTypes.add(type); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/BootstrapOverrideResources.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/BootstrapOverrideResources.java new file mode 100644 index 0000000..0f434e5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/BootstrapOverrideResources.java @@ -0,0 +1,17 @@ +package org.gcube.portlets.user.workspaceexplorerapp.resources; + +/** + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * @Jul 28, 2014 + * + */ +import com.github.gwtbootstrap.client.ui.resources.Resources; +import com.google.gwt.resources.client.TextResource; + +public interface BootstrapOverrideResources extends Resources { + @Source("css/bootstrap.min.css") + TextResource bootstrapCss(); + + @Source("css/gwt-bootstrap.css") + TextResource gwtBootstrapCss(); +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/CustomBootstrapConfigurator.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/CustomBootstrapConfigurator.java new file mode 100644 index 0000000..14ef204 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/CustomBootstrapConfigurator.java @@ -0,0 +1,30 @@ +package org.gcube.portlets.user.workspaceexplorerapp.resources; + + +import com.github.gwtbootstrap.client.ui.config.Configurator; +import com.github.gwtbootstrap.client.ui.resources.Resources; +import com.google.gwt.core.client.GWT; + + +/** + * The Class BootstrapConfigurator. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 10, 2016 + */ +public class CustomBootstrapConfigurator implements Configurator { + + /* (non-Javadoc) + * @see com.github.gwtbootstrap.client.ui.config.Configurator#getResources() + */ + public Resources getResources() { + return GWT.create(BootstrapOverrideResources.class); + } + + /* (non-Javadoc) + * @see com.github.gwtbootstrap.client.ui.config.Configurator#hasResponsiveDesign() + */ + public boolean hasResponsiveDesign() { + return false; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/bootstrap.min.css b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/bootstrap.min.css new file mode 100644 index 0000000..f47623b --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/bootstrap.min.css @@ -0,0 +1,74 @@ +/************************************************* +* +* BOOTSTRAP NO CSS FOR WORKSPACE EXPLORER APP +* +**************************************************/ + +/*ALERTS*/ +.alert { + background-color: #FCF8E3; + border: 1px solid #FBEED5; + border-radius: 4px; + margin-bottom: 20px; + padding: 8px 35px 8px 14px; + text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5); +} + +.alert, .alert h4 { + color: #C09853; +} + +.alert h4 { + margin: 0; +} + +.alert .close { + line-height: 20px; + position: relative; + right: -21px; + top: -2px; +} + +.alert-success { + background-color: #DFF0D8; + border-color: #D6E9C6; + color: #468847; +} + +.alert-success h4 { + color: #468847; +} + +.alert-danger, .alert-error { + background-color: #F2DEDE; + border-color: #EED3D7; + color: #B94A48; +} + +.alert-danger h4, .alert-error h4 { + color: #B94A48; +} + +.alert-info { + background-color: #D9EDF7; + border-color: #BCE8F1; + color: #3A87AD; +} + +.alert-info h4 { + color: #3A87AD; +} + +.alert-block { + padding-bottom: 14px; + padding-top: 14px; +} + +.alert-block>p, .alert-block>ul { + margin-bottom: 0; +} + +.alert-block p+p { + margin-top: 5px; +} + diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/gwt-bootstrap.css b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/gwt-bootstrap.css new file mode 100644 index 0000000..a6671d2 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/resources/css/gwt-bootstrap.css @@ -0,0 +1,80 @@ +/************************************************* +* +* GWT-BOOTSTRAP MINIMAL CSS FOR WORKSPACE EXPLORE +* +**************************************************/ +/* body { */ +/* padding-top: 50px; */ +/* } */ +/* div.input-prepend > input, div.input-prepend > textarea, div.input-prepend > select, div.input-prepend > .uneditable-input { */ +/* margin-bottom: 0; */ +/* } */ +/* div.input-append > input, div.input-append > textarea, div.input-append > select, div.input-append > .uneditable-input { */ +/* margin-bottom: 0; */ +/* } */ +.gwt-PopupPanel .gwt-DatePicker { + width: 200px; +} + +.gwt-SuggestBoxPopup { + z-index: 2100; +} + +.gwt-SuggestBoxPopup .suggestPopupTop { + background-color: #FFFFFF; +} + +.gwt-SuggestBoxPopup .suggestPopupMiddle { + background-color: #FFFFFF; +} + +.gwt-SuggestBoxPopup .suggestPopupBottomCenter { + background-color: #FFFFFF; +} + +.gwt-SuggestBoxPopup .item { + clear: both; + color: #333333; + cursor: pointer; + font-size: 110%; + font-weight: normal; + line-height: 20px; + padding: 3px 9px; + white-space: nowrap; +} + +.gwt-SuggestBoxPopup .item-selected { + background-color: #0081C2; + background-image: linear-gradient(to bottom, #0088CC, #0077B3); + background-repeat: repeat-x; + color: #FFFFFF; + outline: 0 none; + text-decoration: none; +} + +.gwt-TextBox-personal { + background-color: #FFFFFF; + border: 1px solid #CCCCCC; + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset; + transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s; + border-radius: 4px; + color: #555555; + display: inline-block; + font-size: 14px; + height: 20px; + line-height: 20px; + margin-bottom: 10px; + padding: 4px 6px; + vertical-align: middle; +} + +.form-inline input:FOCUS{ + border-color: rgba(82, 168, 236, 0.8); + box-shadow: 0 1px 1px rgba(0, 0, 0, 0.075) inset, 0 0 8px + rgba(82, 168, 236, 0.6); + outline: 0 none +} + +.margin-right-5px { + margin-right: 5px; +} \ No newline at end of file diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/DownloadWorkspaceExplorerServlet.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/DownloadWorkspaceExplorerServlet.java new file mode 100644 index 0000000..5374a26 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/DownloadWorkspaceExplorerServlet.java @@ -0,0 +1,679 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.server; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.StringReader; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.io.IOUtils; +import org.apache.log4j.Logger; +import org.gcube.common.homelibrary.home.exceptions.InternalErrorException; +import org.gcube.common.homelibrary.home.workspace.Workspace; +import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder; +import org.gcube.common.homelibrary.home.workspace.WorkspaceItem; +import org.gcube.common.homelibrary.home.workspace.exceptions.ItemNotFoundException; +import org.gcube.common.homelibrary.home.workspace.folder.FolderItem; +import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalFile; +import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalImage; +import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalUrl; +import org.gcube.common.homelibrary.home.workspace.folder.items.GCubeItem; +import org.gcube.common.homelibrary.home.workspace.folder.items.Query; +import org.gcube.common.homelibrary.home.workspace.folder.items.Report; +import org.gcube.common.homelibrary.home.workspace.folder.items.ReportTemplate; +import org.gcube.common.homelibrary.home.workspace.folder.items.ts.TimeSeries; +import org.gcube.common.homelibrary.util.Extensions; +import org.gcube.common.homelibrary.util.MimeTypeUtil; +import org.gcube.common.homelibrary.util.zip.ZipUtil; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerAppConstants; +import org.gcube.portlets.user.workspaceexplorerapp.shared.HandlerResultMessage; + +/** + * The Class DownloadServlet. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + */ +public class DownloadWorkspaceExplorerServlet extends HttpServlet{ + + /** + * + */ + private static final String ERROR404_HTML = "error404.html"; + + private static final long serialVersionUID = -8423345575690165644L; + + protected static Logger logger = Logger.getLogger(DownloadWorkspaceExplorerServlet.class); + public static final String ERROR_ITEM_DOES_NOT_EXIST = "Item does not exist. It may have been deleted by another user"; + + public static final String REDIRECTONERROR = "redirectonerror"; + + private final String VALIDATEITEM = WorkspaceExplorerAppConstants.VALIDATEITEM; + private final String IDS = WorkspaceExplorerAppConstants.IDS; + private final String IDS_SEPARATOR = WorkspaceExplorerAppConstants.IDS_SEPARATOR; + /** + * {@inheritDoc} + */ + @Override + public void init() throws ServletException { + super.init(); + logger.trace("Workspace DownloadServlet ready."); + } + + + /* (non-Javadoc) + * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { + + String itemIds = req.getParameter(IDS); + boolean viewContent = req.getParameter("viewContent")==null?false:req.getParameter("viewContent").equals("true"); + boolean isValidItem = req.getParameter(VALIDATEITEM)==null?false:req.getParameter(VALIDATEITEM).equals("true"); + boolean urlRedirectOnError = req.getParameter(REDIRECTONERROR)==null?false:req.getParameter(REDIRECTONERROR).equals("true"); + + logger.trace("Input Params [ids: "+itemIds + ", viewContent: "+viewContent+", "+VALIDATEITEM +": " +isValidItem+", urlRedirectOnError:" +urlRedirectOnError+"]"); + if(itemIds==null || itemIds.isEmpty()){ + sendError(resp,HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Item id is null"); + return; + } + + logger.trace("FILE DOWNLOAD REQUEST "+itemIds); + List ids = toList(itemIds, IDS_SEPARATOR); + Workspace wa = null; + try { + + wa = WsUtil.getWorkspace(req.getSession()); + } catch (Exception e) { + + /*if (e instanceof SessionExpiredException){ + sendErrorForStatus(resp, HttpServletResponse.SC_UNAUTHORIZED +": Session expired", HttpServletResponse.SC_UNAUTHORIZED); + return; + }*/ + + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during workspace retrieving"); + return; + } + + if (wa == null) { + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error, no workspace in session"); + return; + } + + WorkspaceItem item; + try { + + //MULTIPLE DOWNLOAD - CREATE A ZIP FOR SUCH WORKSPACE IDs AND RETURN + if(ids.size()>1){ + List listWI = toWorkspaceItems(wa, ids); + try { + File tmpZip = ZipUtil.zipWorkspaceItems(listWI, null); + resp.setHeader( "Content-Disposition", "attachment; filename=\"gCube Workspace Files - " + new Date() +".zip\"" ); + resp.setContentType("application/zip"); + resp = setContentLength(resp, tmpZip.length()); + OutputStream out = resp.getOutputStream(); + + FileInputStream fileTmpZip = new FileInputStream(tmpZip); + IOUtils.copy(fileTmpZip, resp.getOutputStream()); + fileTmpZip.close(); + + out.close(); + tmpZip.delete(); + return; + } + catch (InternalErrorException e) { + logger.error("Error during folder compression "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during folder compression: "+e.getMessage()); + return; + } + + } + + //SINGLE DONWLOAD - DOWNLOAD WORKSPACE ITEM + item = wa.getItem(ids.get(0)); + if(isValidItem){ //ADDED 25/06/2013 - THIS CODE RETURN A SC_ACCEPT IS ITEM EXIST + String message = HttpServletResponse.SC_ACCEPTED+ ": The resource is available"; + sendMessageResourceAvailable(resp, message); + logger.trace("response return: "+message); + return; + } + + try{ + //ACCOUNTING + item.markAsRead(true); + } catch (InternalErrorException e) { + logger.error("Requested item "+itemIds+" has thrown an internal error exception",e); + } + + } catch (ItemNotFoundException e) { + logger.error("Requested item "+itemIds+" not found",e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": The file has been deleted by another user."); + return; + } + + switch (item.getType()) { + + case SHARED_FOLDER: + case FOLDER:{ + try { + File tmpZip = ZipUtil.zipFolder((WorkspaceFolder) item); + resp.setHeader( "Content-Disposition", "attachment; filename=\"" + item.getName() + ".zip\"" ); + resp.setContentType("application/zip"); + resp = setContentLength(resp, tmpZip.length()); + OutputStream out = resp.getOutputStream(); + + FileInputStream fileTmpZip = new FileInputStream(tmpZip); + IOUtils.copy(fileTmpZip, resp.getOutputStream()); + fileTmpZip.close(); + + out.close(); + tmpZip.delete(); + return; + + } catch (Exception e) { + logger.error("Error during folder compression "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during folder compression: "+e.getMessage()); + return; + } + } + case FOLDER_ITEM:{ + FolderItem folderItem = (FolderItem) item; + + switch (folderItem.getFolderItemType()) { + + case REPORT_TEMPLATE:{ + try{ + ReportTemplate reportTemplate = (ReportTemplate)folderItem; + String extension = FilenameUtils.getExtension(item.getName()); + String itemName = item.getName(); + logger.trace("case REPORT_TEMPLATE extension is" +extension); + + if(extension.compareToIgnoreCase(Extensions.REPORT_TEMPLATE.getName())!=0) //ADD EXTENSION? + itemName = "." + Extensions.REPORT_TEMPLATE.getName(); + + logger.trace("case REPORT_TEMPLATE itemName is" +extension); + String contentDisposition = viewContent?"inline":"attachment"; + resp.setHeader( "Content-Disposition", contentDisposition+"; filename=\"" + itemName + "\"" ); + + resp.setContentType("application/zip"); + resp = setContentLength(resp, reportTemplate.getLength()); + OutputStream out = resp.getOutputStream(); + + //MODIFIED 22-05-2013 CLOSE STREAM + InputStream is = reportTemplate.getData(); + IOUtils.copy(is, resp.getOutputStream()); + is.close(); + + out.close(); + } catch (Exception e) { + logger.error("Error during external item sending "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + return; + + } + case REPORT:{ + try{ + Report report = (Report)folderItem; + String extension = FilenameUtils.getExtension(item.getName()); + String itemName = item.getName(); + logger.trace("case REPORT extension is" +extension); + + if(extension.compareToIgnoreCase(Extensions.REPORT.getName())!=0) //ADD EXTENSION? + itemName = "." + Extensions.REPORT.getName(); + + logger.trace("case REPORT itemName is" +extension); + String contentDisposition = viewContent?"inline":"attachment"; + resp.setHeader( "Content-Disposition", contentDisposition+"; filename=\"" + itemName + "\"" ); + + resp.setContentType("application/zip"); + resp = setContentLength(resp, report.getLength()); + OutputStream out = resp.getOutputStream(); + + //MODIFIED 22-05-2013 CLOSE STREAM + InputStream is = report.getData(); + IOUtils.copy(is, resp.getOutputStream()); + is.close(); + + out.close(); + } catch (Exception e) { + logger.error("Error during external item sending "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + return; + + } + case EXTERNAL_PDF_FILE: + case EXTERNAL_FILE:{ + + InputStream is = null; + OutputStream out = null; + try{ + ExternalFile externalFile = (ExternalFile)folderItem; + + String mimeType = externalFile.getMimeType(); + + logger.trace("EXTERNAL_FILE DOWNLOAD FOR "+externalFile.getId()); + String contentDisposition = viewContent?"inline":"attachment"; + resp.setHeader("Content-Disposition", contentDisposition+"; filename=\"" + item.getName() + "\"" ); + resp.setContentType(mimeType); + resp = setContentLength(resp, externalFile.getLength()); + is = externalFile.getData(); + out = resp.getOutputStream(); + IOUtils.copy(is, out); + + is.close(); + out.close(); + + } catch (Exception e) { + logger.error("Error during external item retrieving "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + return; + + } + case EXTERNAL_IMAGE:{ + + try{ + ExternalImage externalImage = (ExternalImage)folderItem; + + String mimeType = externalImage.getMimeType(); + String itemName = MimeTypeUtil.getNameWithExtension(item.getName(), mimeType); + + String contentDisposition = viewContent?"inline":"attachment"; + resp.setHeader( "Content-Disposition", contentDisposition+"; filename=\"" + itemName + "\"" ); + resp.setContentType(externalImage.getMimeType()); + resp = setContentLength(resp, externalImage.getLength()); + OutputStream out = resp.getOutputStream(); + InputStream is = externalImage.getData(); + IOUtils.copy(is, out); + is.close(); + + out.close(); + return; + } catch (Exception e) { + logger.error("Error during item retrieving "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + } + case EXTERNAL_URL:{ + try{ + ExternalUrl externalUrl = (ExternalUrl)folderItem; + + String itemName = MimeTypeUtil.getNameWithExtension(externalUrl.getName(), "text/uri-list"); + String contentDisposition = viewContent?"inline":"attachment"; + resp.setHeader("Content-Disposition", contentDisposition+"; filename=\"" + itemName + "\"" ); + resp.setContentType("text/uri-list"); + resp = setContentLength(resp, externalUrl.getLength()); + + //MODIFIED 22-05-2013 CLOSE STREAM + StringReader sr = new StringReader(externalUrl.getUrl()); + OutputStream out = resp.getOutputStream(); + IOUtils.copy(sr, out); + + sr.close(); + out.close(); + return; + } catch (Exception e) { + logger.error("Error during item retrieving "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + } + case QUERY:{ + + Query query = (Query)folderItem; + resp.setContentType("text/plain"); + try { + resp = setContentLength(resp, query.getLength()); + } catch (Exception e) { + logger.error("Error getting item lenght "+query,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + + //MODIFIED 22-05-2013 CLOSE STREAM + OutputStream out = resp.getOutputStream(); + StringReader sr = new StringReader(query.getQuery()); + IOUtils.copy(sr, out); + sr.close(); + + out.close(); + return; + + } + case TIME_SERIES:{ + try{ + TimeSeries ts = (TimeSeries)folderItem; + File tmpZip = ZipUtil.zipTimeSeries(ts); + + String contentDisposition = viewContent?"inline":"attachment"; + resp.setHeader( "Content-Disposition", contentDisposition+"; filename=\"" + item.getName() + ".zip\"" ); + resp.setContentType("application/zip"); + resp = setContentLength(resp, tmpZip.length()); + + //MODIFIED 22-05-2013 CLOSE STREAM + OutputStream out = resp.getOutputStream(); + FileInputStream fileTmpZip = new FileInputStream(tmpZip); + IOUtils.copy(fileTmpZip, out); + fileTmpZip.close(); + + out.close(); + tmpZip.delete(); + return; + } catch (Exception e) { + logger.error("Error during item retrieving "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + } + case IMAGE_DOCUMENT: + case PDF_DOCUMENT: + case URL_DOCUMENT: + case DOCUMENT:{ + try{ +// Document document = (Document)item; + GCubeItem document = (GCubeItem) item; //Cast GCubeItem + + if (!viewContent){ + File tmpZip = ZipUtil.zipDocument(document); + + resp.setHeader( "Content-Disposition", "attachment; filename=\"" + item.getName() + ".zip\"" ); + resp.setContentType("application/zip"); + resp = setContentLength(resp, tmpZip.length()); + + //MODIFIED 22-05-2013 CLOSE STREAM + OutputStream out = resp.getOutputStream(); + FileInputStream fileTmpZip = new FileInputStream(tmpZip); + IOUtils.copy(fileTmpZip, out); + fileTmpZip.close(); + + out.close(); + tmpZip.delete(); + } + else{ + String mimeType = document.getMimeType(); + String itemName = MimeTypeUtil.getNameWithExtension(item.getName(), mimeType); + resp.setHeader( "Content-Disposition", "inline; filename=\"" + itemName + "\"" ); + resp.setContentType(document.getMimeType()); + resp = setContentLength(resp, document.getLength()); + //MODIFIED 22-05-2013 CLOSE STREAM + OutputStream out = resp.getOutputStream(); + InputStream is = document.getData(); + IOUtils.copy(is, out); + is.close(); + + out.close(); + } + return; + } catch (Exception e) { + logger.error("Error during item retrieving "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + } + + case METADATA:{ + try{ +// Metadata document = (Metadata)item; + GCubeItem metadata = (GCubeItem) item; //Cast GCubeItem + + resp.setContentType("text/html"); + resp = setContentLength(resp, metadata.getLength()); + + //MODIFIED 22-05-2013 CLOSE STREAM + OutputStream out = resp.getOutputStream(); + InputStream is = metadata.getData(); + IOUtils.copy(is, out); + is.close(); + out.close(); + + return; + } catch (Exception e) { + logger.error("Error during item retrieving "+itemIds,e); + handleError(urlRedirectOnError, req, resp, itemIds, HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving: "+e.getMessage()); + return; + } + } + } + + } + } + + handleError(urlRedirectOnError, req, resp, itemIds,HttpServletResponse.SC_INTERNAL_SERVER_ERROR +": Error during data retrieving"); + return; + } + + + /** + * To list. + * + * @param ids the ids + * @param separator the separator + * @return the list + */ + private static List toList(String ids, String separator){ + + String[] toArray = ids.split(separator); + List lstIds = new ArrayList(toArray.length); + for (String id : toArray) { + if(id!=null && !id.isEmpty()) + lstIds.add(id); + } + logger.trace("ids to list: "+lstIds); + return lstIds; + } + + + /** + * To workspace items. + * + * @param ws the ws + * @param workspaceItemIds the workspace item ids + * @return the list + */ + private List toWorkspaceItems(Workspace ws, List workspaceItemIds){ + + if(workspaceItemIds==null) + return null; + + List listWI = new ArrayList(workspaceItemIds.size()); + + for (String wsId : workspaceItemIds) { + try{ + listWI.add(ws.getItem(wsId)); + }catch(Exception e){ + logger.warn("Error on getting item id: "+wsId +", skipping item"); + } + } + return listWI; + } + + /** + * Method to manage HttpServletResponse content length also to big data. + * + * @param resp the resp + * @param length the length + * @return the http servlet response + */ + protected HttpServletResponse setContentLength(HttpServletResponse resp, long length){ + try{ + if (length <= Integer.MAX_VALUE) + resp.setContentLength((int)length); + else + resp.addHeader("Content-Length", Long.toString(length)); + }catch(Exception e){ + //silent + } + return resp; + } + + /** + * Handle error. + * + * @param urlRedirectOnError the url redirect on error + * @param req the req + * @param resp the resp + * @param itemId the item id + * @param message the message + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void handleError(boolean urlRedirectOnError, HttpServletRequest req, HttpServletResponse resp, String itemId, String message) throws IOException{ + + logger.warn("Handle error occurred: "+message); + logger.trace("urlRedirectOnError is active: "+urlRedirectOnError); + if(urlRedirectOnError){ + urlRedirect(req, resp, ERROR404_HTML); + }else + sendError(resp,message); + + } + + /** + * Send error. + * + * @param response the response + * @param message the message + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendError(HttpServletResponse response, String message) throws IOException + { + response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + HandlerResultMessage resultMessage = HandlerResultMessage.errorResult(message); + logger.trace("error message: "+resultMessage); + logger.trace("writing response..."); + StringReader sr = new StringReader(resultMessage.toString()); + IOUtils.copy(sr, response.getOutputStream()); + + logger.trace("response writed"); + response.flushBuffer(); + } + + + /** + * Send error for status. + * + * @param response the response + * @param message the message + * @param status the status + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendErrorForStatus(HttpServletResponse response, String message, int status) throws IOException + { + response.setStatus(status); + HandlerResultMessage resultMessage = HandlerResultMessage.errorResult(message); + logger.trace("error message: "+resultMessage); + logger.trace("writing response..."); + StringReader sr = new StringReader(resultMessage.toString()); + IOUtils.copy(sr, response.getOutputStream()); + + logger.trace("response writed"); + response.flushBuffer(); + } + + /** + * Send message. + * + * @param response the response + * @param message the message + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendMessage(HttpServletResponse response, String message) throws IOException + { + response.setStatus(HttpServletResponse.SC_ACCEPTED); + HandlerResultMessage resultMessage = HandlerResultMessage.okResult(message); + response.getWriter().write(resultMessage.toString()); + response.flushBuffer(); + } + + /** + * Send message resource available. + * + * @param response the response + * @param message the message + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendMessageResourceAvailable(HttpServletResponse response, String message) throws IOException + { + response.setStatus(HttpServletResponse.SC_ACCEPTED); + HandlerResultMessage resultMessage = HandlerResultMessage.okResult(message); + response.getWriter().write(resultMessage.toString()); + response.flushBuffer(); + } + + /** + * Send warn message. + * + * @param response the response + * @param message the message + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void sendWarnMessage(HttpServletResponse response, String message) throws IOException + { + response.setStatus(HttpServletResponse.SC_ACCEPTED); + HandlerResultMessage resultMessage = HandlerResultMessage.warnResult(message); + response.getWriter().write(resultMessage.toString()); + response.flushBuffer(); + } + + /** + * Url redirect. + * + * @param req the req + * @param response the response + * @param errorPage the error page + * @throws IOException Signals that an I/O exception has occurred. + */ + protected void urlRedirect(HttpServletRequest req, HttpServletResponse response, String errorPage) throws IOException { + + String requestUrl = getRedirectURL(req) +errorPage; + logger.trace("Url redirect on: "+requestUrl); +// System.out.println("Url redirect on: "+requestUrl); + response.sendRedirect(response.encodeRedirectURL(requestUrl)); + return; + } + + /** + * Gets the redirect url. + * + * @param req the req + * @return the redirect url + */ + public static String getRedirectURL(HttpServletRequest req) { + + String scheme = req.getScheme(); // http + String serverName = req.getServerName(); // hostname.com + int serverPort = req.getServerPort(); // 80 + String contextPath = req.getContextPath(); // /mywebapp +// String servletPath = req.getServletPath(); // /servlet/MyServlet +// String pathInfo = req.getPathInfo(); // /a/b;c=123 +// String queryString = req.getQueryString(); // d=789 + + // Reconstruct original requesting URL + StringBuffer url = new StringBuffer(); + url.append(scheme).append("://").append(serverName); + + if (serverPort != 80 && serverPort != 443) { + url.append(":").append(serverPort); + } + + url.append("/").append(contextPath); + logger.trace("returning url: "+url); + return url.toString(); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemBuilder.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemBuilder.java new file mode 100644 index 0000000..1f2f933 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemBuilder.java @@ -0,0 +1,400 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.server; + +import java.util.Calendar; +import java.util.Date; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.gcube.common.homelibary.model.items.type.WorkspaceItemType; +import org.gcube.common.homelibrary.home.exceptions.InternalErrorException; +import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder; +import org.gcube.common.homelibrary.home.workspace.WorkspaceItem; +import org.gcube.common.homelibrary.home.workspace.WorkspaceSharedFolder; +import org.gcube.common.homelibrary.home.workspace.folder.FolderItem; +import org.gcube.common.homelibrary.home.workspace.folder.items.ExternalFile; +import org.gcube.portlets.user.workspaceexplorerapp.client.Util; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerAppConstants; +import org.gcube.portlets.user.workspaceexplorerapp.shared.FilterCriteria; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * The Class ItemBuilder. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 22, 2016 + */ +public class ItemBuilder { + + public static final Logger _log = LoggerFactory.getLogger(ItemBuilder.class); + /** + * Purge empty folders. + * + * @param item the item + * @return the item + */ + public static Item purgeEmptyFolders(Item item) + { + //for (Item child:item.getChildren()) purgeEmptyFolders(child); ONLY FIRST LEVEL + + List toRemoveList = new LinkedList(); + for (Item child:item.getChildren()) { + boolean toRemove = isAnEmptyFolder(child); + if (toRemove) { + toRemoveList.add(child); + } + } + for (Item child:toRemoveList) { + item.removeChild(child); + } + + return item; + } + + + /** + * Checks if is an empty folder. + * + * @param item the item + * @return true, if is an empty folder + */ + protected static boolean isAnEmptyFolder(Item item) + { + return Util.isFolder(item.getType()) && item.getChildren().size() == 0; + } + + + /** + * Gets the item. + * + * @param parent the parent + * @param workspaceItem the workspace item + * @param workspaceItemPath the workspace item path + * @param showableTypes the showable types + * @param filterCriteria the filter criteria + * @param loadChildren the load children + * @return the item + * @throws InternalErrorException the internal error exception + */ + public static Item getItem(Item parent, WorkspaceItem workspaceItem, String workspaceItemPath, List showableTypes, FilterCriteria filterCriteria, boolean loadChildren) throws InternalErrorException + { + + ItemType type = getItemType(workspaceItem); + + if (!showableTypes.contains(type)) { + return null; + } + if (!filterItem(type, workspaceItem, filterCriteria)) { + return null; + } + +// //TODO ADD CONTROL ON THE PATH WHEN WILL BE MORE FAST +// if (itemName.equals(WorkspaceExplorerConstants.SPECIAL_FOLDERS_LABEL)) +// itemName = WorkspaceExplorerConstants.VRE_FOLDERS_LABEL; + + boolean isFolder = type.equals(ItemType.FOLDER)?true:false; + boolean isSharedFolder = workspaceItem.getType().equals(WorkspaceItemType.SHARED_FOLDER)?true:false; + + String itemName = workspaceItem.getName(); + + if(isSharedFolder){ + _log.debug("Is shared folder"); + WorkspaceSharedFolder shared = (WorkspaceSharedFolder) workspaceItem; + itemName = shared.isVreFolder()?shared.getDisplayName():workspaceItem.getName(); + } + +// _log.debug("Building Item for: "+itemName); + Item item = null; + try{ + + item = new Item(parent, workspaceItem.getId(), itemName, type, workspaceItemPath, workspaceItem.getOwner().getPortalLogin(), toDate(workspaceItem.getCreationTime()), isFolder, false); + item.setSharedFolder(isSharedFolder); + }catch(Exception e){ + _log.error("Error on getting item: "+itemName+" with id: "+workspaceItem.getId()+", from HL, so skipping item"); + return null; + } + + if(loadChildren){ + //TODO A PATCH TO AVOID A SLOW GETPATH +// workspaceItemPath = workspaceItem.getPath(); + for (WorkspaceItem child: workspaceItem.getChildren()){ + String itemPath = workspaceItemPath; + if(child.isFolder()) + itemPath+="/"+child.getName(); + +// _log.trace("\nConverting child item: "+child.getName()); + Item itemChild = getItem(item, child, itemPath, showableTypes, filterCriteria, false); +// _log.trace("Item: "+child.getName() +" converted!!!"); + if (itemChild!=null){ + item.addChild(itemChild); + } + } + } + + return item; + } + + + /** + * To date. + * + * @param calendar the calendar + * @return the date + */ + public static Date toDate(Calendar calendar) + { + if (calendar == null) return null; + return calendar.getTime(); + + } + + /** + * Gets the item type. + * + * @param item the item + * @return the item type + * @throws InternalErrorException the internal error exception + */ + protected static ItemType getItemType(WorkspaceItem item) throws InternalErrorException + { + switch(item.getType()) + { + case SHARED_FOLDER: + case FOLDER:{ +// if (item.isRoot()) return ItemType.ROOT; + return ItemType.FOLDER; + } + case FOLDER_ITEM: return getFolderItemType((FolderItem) item); + + default: + return null; + } + } + + /** + * Gets the folder item type. + * + * @param item the item + * @return the folder item type + */ + protected static ItemType getFolderItemType(FolderItem item){ + + try{ + return ItemType.valueOf(item.getFolderItemType().toString()); + }catch (Exception e) { + _log.error("Item Type non found: ",e); + return ItemType.UNKNOWN_TYPE; + } + } + + + /** + * Filter item. + * + * @param type the type + * @param item the item + * @param filterCriteria the filter criteria + * @return true, if successful + * @throws InternalErrorException the internal error exception + */ + protected static boolean filterItem(ItemType type, WorkspaceItem item, FilterCriteria filterCriteria) throws InternalErrorException { + if(filterCriteria==null) { + return true; + } + + boolean mimeTypeCheck = checkAllowedMimeTypes(type, item, filterCriteria.getAllowedMimeTypes()); + if (!mimeTypeCheck) { + return false; + } + + boolean fileExtensionCheck = checkAllowedFileExtension(type, item, filterCriteria.getAllowedFileExtensions()); + if(!fileExtensionCheck) { + return false; + } + + boolean propertiesCheck = checkProperties(item, filterCriteria.getRequiredProperties()); + return propertiesCheck; + } + + /** + * Check allowed mime types. + * + * @param type the type + * @param item the item + * @param allowedMimeTypes the allowed mime types + * @return true, if successful + */ + protected static boolean checkAllowedMimeTypes(ItemType type, WorkspaceItem item, List allowedMimeTypes){ + if (allowedMimeTypes==null || allowedMimeTypes.size()==0) { + return true; + } + + if (type == ItemType.EXTERNAL_FILE || type == ItemType.EXTERNAL_IMAGE || type == ItemType.EXTERNAL_PDF_FILE) { + ExternalFile externalFile = (ExternalFile)item; + String mimeType = externalFile.getMimeType(); + return allowedMimeTypes.contains(mimeType); + } + return true; + } + + + + + /** + * Check allowed file extension. + * + * @param type the type + * @param item the item + * @param allowedFileExtension the allowed mime types + * @return true, if successful + */ + protected static boolean checkAllowedFileExtension(ItemType type, WorkspaceItem item, List allowedFileExtension){ + if (allowedFileExtension==null || allowedFileExtension.size()==0) { + return true; + } + + try { + if (type != ItemType.FOLDER) { + String name = item.getName(); + return checkFileExtension(name, allowedFileExtension); + } + return true; + } catch (InternalErrorException e) { + _log.error("checkAllowedFileExtension, InternalErrorException: ",e); + return false; + } + } + + /** + * Check file extension. + * + * @param fileName the file name + * @param allowedFileExtension the allowed file extension + * @return true, if successful + */ + protected static boolean checkFileExtension(String fileName, List allowedFileExtension){ + + if(fileName==null || fileName.isEmpty()) { + return false; + } + + int dot = fileName.lastIndexOf("."); + if(dot>=0 && dot+1<=fileName.length()){ + + String ext = fileName.substring(dot+1, fileName.length()); + _log.trace("Extension found: "+ext +" for: "+fileName); +// if(ext.isEmpty()) +// return false; + for (String fe : allowedFileExtension) { + if(ext.compareTo(fe)==0) { + return true; + } + } + return false; + } + _log.trace("Extension not found for: "+fileName); + return false; + } + + + /** + * Check properties. + * + * @param item the item + * @param requestedProperties the requested properties + * @return true, if successful + * @throws InternalErrorException the internal error exception + */ + protected static boolean checkProperties(WorkspaceItem item, Map requestedProperties) throws InternalErrorException + { + if (requestedProperties==null || requestedProperties.size()==0 || item.getType()!=WorkspaceItemType.FOLDER_ITEM) { + return true; + } + + Map itemProperties = item.getProperties().getProperties(); + for (Entry requestProperty:requestedProperties.entrySet()) { + String propertyValue = itemProperties.get(requestProperty.getKey()); + if (propertyValue == null) { + return false; + } + if (!propertyValue.equals(requestProperty.getValue())) { + return false; + } + } + + return true; + } + + + + /** + * Builds the folder to breadcrumbs. + * + * @param wsFolder the ws folder + * @param parent the parent + * @return the item + * @throws InternalErrorException the internal error exception + */ + public static Item buildFolderForBreadcrumbs(WorkspaceFolder wsFolder, Item parent) throws InternalErrorException { + + String name = ""; + boolean isSpecialFolder = false; + boolean isRoot = false; + + if(wsFolder.isRoot()){ //IS ROOT + name = WorkspaceExplorerAppConstants.HOME_LABEL; + isRoot = true; + }else if(wsFolder.isShared() && wsFolder.getType().equals(WorkspaceItemType.SHARED_FOLDER)){ //MANAGEMENT SHARED FOLDER NAME + WorkspaceSharedFolder shared = (WorkspaceSharedFolder) wsFolder; + name = shared.isVreFolder()?shared.getDisplayName():wsFolder.getName(); + //MANAGEMENT SPECIAL FOLDER + }else if(isSpecialFolder(wsFolder)){ + name = WorkspaceExplorerAppConstants.VRE_FOLDERS_LABEL; + isSpecialFolder = true; + } + else { + name = wsFolder.getName(); + } + + //BUILDS A SIMPLE ITEM FOR BREADCRUMB + String path = null; //wsFolder.getPath(); FORCED TO NULL BECAUSE IS SLOW CALL + Item item = new Item(null, wsFolder.getId(), name, ItemType.FOLDER, path, null, null, true, isRoot); + item.setSpecialFolder(isSpecialFolder); + + _log.debug("breadcrumb returning: "+item); + return item; + } + + /** + * Checks if is special folder. + * + * @param wsFolder the ws folder + * @return true, if is special folder + */ + public static boolean isSpecialFolder(WorkspaceFolder wsFolder){ + + try { + return wsFolder.getName().compareTo(WorkspaceExplorerAppConstants.SPECIAL_FOLDERS_NAME)==0 && wsFolder.getParent()!=null && wsFolder.getParent().isRoot(); + } catch (InternalErrorException e) { + _log.warn("isSpecialFolder exception, returning false"); + return false; + } + } + /* + public static void main(String[] args) { + List allowedFileExtension = new ArrayList(); + allowedFileExtension.add("csv"); + allowedFileExtension.add(""); + + String fileName = "t"; + System.out.println(checkFileExtension(fileName, allowedFileExtension)); + }*/ +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemComparator.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemComparator.java new file mode 100644 index 0000000..945d812 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/ItemComparator.java @@ -0,0 +1,46 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.server; + +import java.util.Comparator; + +import org.gcube.portlets.user.workspaceexplorerapp.client.Util; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerAppConstants; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; + + +/** + * A comparator that sorts the items first by type, folder up others down, the each group alphabetically on the item name. + * @author "Federico De Faveri defaveri@isti.cnr.it" + */ +public class ItemComparator implements Comparator { + + /** + * {@inheritDoc} + */ + @Override + public int compare(Item item1, Item item2) { + + //if one of the item is folder and the other one not, we move up the folder + boolean isItem1Folder = Util.isFolder(item1.getType()); + boolean isItem2Folder = Util.isFolder(item2.getType()); + + boolean isSpecialFolder1 = isSpecialFolder(item1); + boolean isSpecialFolder2 = isSpecialFolder(item2); + + //XOR + if (isSpecialFolder1 ^ isSpecialFolder2) return isSpecialFolder1 ? -1 : 1; + + //XOR + if (isItem1Folder ^ isItem2Folder) return isItem1Folder ? -1 : 1; + + //otherwise we compare the names + return String.CASE_INSENSITIVE_ORDER.compare(item1.getName(), item2.getName()); + } + + private boolean isSpecialFolder(Item item) { +// return item.getName().equals(WorkspaceExplorerConstants.VRE_FOLDERS_LABEL) && item.getParent()!=null && item.getParent().isRoot(); + return item.getName().equals(WorkspaceExplorerAppConstants.VRE_FOLDERS_LABEL) && item.isSpecialFolder(); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/StringUtil.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/StringUtil.java new file mode 100644 index 0000000..a2fd1cb --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/StringUtil.java @@ -0,0 +1,31 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.server; + +import java.text.DecimalFormat; + + +/** + * The Class StringUtil. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 22, 2016 + */ +public class StringUtil { + + /** + * Readable file size. + * + * @param size the size + * @return the string + */ + public static String readableFileSize(long size) { + if(size < 0) return "Unknown"; + if(size == 0) return "0"; + final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" }; + int digitGroups = (int) (Math.log10(size)/Math.log10(1024)); + return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups))+units[digitGroups]; + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WorkspaceExplorerAppServiceImpl.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WorkspaceExplorerAppServiceImpl.java new file mode 100644 index 0000000..cd52bd5 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WorkspaceExplorerAppServiceImpl.java @@ -0,0 +1,644 @@ +package org.gcube.portlets.user.workspaceexplorerapp.server; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import org.gcube.application.framework.core.session.ASLSession; +import org.gcube.common.homelibary.model.items.type.WorkspaceItemType; +import org.gcube.common.homelibrary.home.HomeLibrary; +import org.gcube.common.homelibrary.home.workspace.Workspace; +import org.gcube.common.homelibrary.home.workspace.WorkspaceFolder; +import org.gcube.common.homelibrary.home.workspace.WorkspaceItem; +import org.gcube.common.homelibrary.home.workspace.WorkspaceSharedFolder; +import org.gcube.common.homelibrary.home.workspace.exceptions.InsufficientPrivilegesException; +import org.gcube.common.homelibrary.home.workspace.exceptions.ItemAlreadyExistException; +import org.gcube.common.homelibrary.home.workspace.folder.FolderItem; +import org.gcube.portlets.user.workspaceexplorerapp.client.WorkspaceExplorerAppConstants; +import org.gcube.portlets.user.workspaceexplorerapp.client.rpc.WorkspaceExplorerAppService; +import org.gcube.portlets.user.workspaceexplorerapp.shared.FilterCriteria; +import org.gcube.portlets.user.workspaceexplorerapp.shared.Item; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemCategory; +import org.gcube.portlets.user.workspaceexplorerapp.shared.ItemType; +import org.gcube.portlets.user.workspaceexplorerapp.shared.WorkspaceNavigatorServiceException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.gwt.user.server.rpc.RemoteServiceServlet; + +/** + * The server side implementation of the RPC service. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 25, 2015 + */ +@SuppressWarnings("serial") +public class WorkspaceExplorerAppServiceImpl extends RemoteServiceServlet implements WorkspaceExplorerAppService { + + /** + * + */ + public static final Logger logger = LoggerFactory.getLogger(WorkspaceExplorerAppServiceImpl.class); + + + + /** + * {@inheritDoc} + */ + @Override + public Item getRoot(List showableTypes, boolean purgeEmpyFolders, FilterCriteria filterCriteria) throws WorkspaceNavigatorServiceException { + logger.trace("getRoot showableTypes: "+showableTypes+" purgeEmpyFolders: "+purgeEmpyFolders+" filterCriteria: "+ filterCriteria); + + try { + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + logger.trace("Start getRoot..."); + + WorkspaceItem root = workspace.getRoot(); + + logger.trace("GetRoot - Replyiing root"); + long startTime = System.currentTimeMillis(); + logger.trace("start time - " + startTime); + + Item rootItem = ItemBuilder.getItem(null, root, root.getPath(), showableTypes, filterCriteria, true); + rootItem.setName(WorkspaceExplorerAppConstants.HOME_LABEL); + rootItem.setIsRoot(true); + + /* SPECIAL FOLDERS + Item specialFolders = ItemBuilder.getItem(null, specials, showableTypes, filterCriteria, 2); + specialFolders.setShared(true); + rootItem.addChild(specialFolders); + */ + if (purgeEmpyFolders) { + rootItem = ItemBuilder.purgeEmptyFolders(rootItem); + } + + logger.trace("Returning:"); + Long endTime = System.currentTimeMillis() - startTime; + String time = String.format("%d msc %d sec", endTime, TimeUnit.MILLISECONDS.toSeconds(endTime)); + logger.info("end time - " + time); + + Collections.sort(rootItem.getChildren(), new ItemComparator()); + logger.info("Returning children size: "+rootItem.getChildren().size()); + + return rootItem; + + } catch (Exception e) { + logger.error("Error during root retrieving", e); + throw new WorkspaceNavigatorServiceException("Sorry, an error occurred when performing get root"); + } + } + + /** + * {@inheritDoc} + */ + @Override + public Item getFolder(Item item, List showableTypes, boolean purgeEmpyFolders, FilterCriteria filterCriteria) throws WorkspaceNavigatorServiceException { + logger.trace("getFolder item: "+item+" showableTypes: "+showableTypes+" purgeEmpyFolders: "+purgeEmpyFolders+" filterCriteria: "+filterCriteria); + + try { + + if(item==null || item.getId()==null) + throw new Exception("Item id is null"); + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem folder = workspace.getItem(item.getId()); + + logger.trace("GetFolder - Replyiing folder"); + long startTime = System.currentTimeMillis(); + logger.trace("start time - " + startTime); + + String path = item.getPath()!=null && !item.getPath().isEmpty()?item.getPath():folder.getPath(); + + Item itemFolder = ItemBuilder.getItem(null, folder, path, showableTypes, filterCriteria, true); +// _log.trace("Only showable types:"); + + if (purgeEmpyFolders) { + itemFolder = ItemBuilder.purgeEmptyFolders(itemFolder); + } + + logger.trace("Returning:"); + Long endTime = System.currentTimeMillis() - startTime; + String time = String.format("%d msc %d sec", endTime, TimeUnit.MILLISECONDS.toSeconds(endTime)); + logger.info("end time - " + time); + + Collections.sort(itemFolder.getChildren(), new ItemComparator()); + + return itemFolder; + + } catch (Exception e) { + logger.error("Error during folder retrieving", e); + throw new WorkspaceNavigatorServiceException("Sorry, an error occurred when performing get folder"); + } + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.rpc.WorkspaceExplorerService#getItemByCategory(org.gcube.portlets.widgets.wsexplorer.shared.ItemCategory) + */ + @Override + public Item getItemByCategory(ItemCategory category) throws WorkspaceNavigatorServiceException{ + logger.trace("GetItemByCategory category: "+category); + try { + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + Item item = null; + + switch(category){ + case HOME:{ + WorkspaceItem root = workspace.getRoot(); + ASLSession session = WsUtil.getASLSession(this.getThreadLocalRequest().getSession()); +// String fullName = UserUtil.getUserFullName(session.getUsername()); + String fullName = session.getUsername(); + if(fullName.indexOf(" ")>0){ + fullName = fullName.substring(0, fullName.indexOf(" ")); + }else if(fullName.indexOf(".")>0){ + fullName = fullName.substring(0, fullName.indexOf(".")); + } + item = new Item(null, root.getId(), fullName+"'s", ItemType.FOLDER, root.getPath(), root.getOwner().getPortalLogin(), null, true, true); + break; + } + case VRE_FOLDER:{ + WorkspaceItem folder = workspace.getMySpecialFolders(); + item = new Item(null, folder.getId(), WorkspaceExplorerAppConstants.VRE_FOLDERS_LABEL, ItemType.FOLDER, folder.getPath(), folder.getOwner().getPortalLogin(), null, true, false); + //SET SPECIAL FOLDER /Workspace/MySpecialFolders + item.setSpecialFolder(true); + break; + } + } + return item; + } catch (Exception e) { + logger.error("Error during get item by category", e); + throw new WorkspaceNavigatorServiceException("Sorry, an error occurred when performing get item by category"); + } + } + + /** + * {@inheritDoc} + */ + @Override + public Item getMySpecialFolder(List showableTypes, boolean purgeEmpyFolders, FilterCriteria filterCriteria) throws WorkspaceNavigatorServiceException { + logger.trace("GetMySpecialFolder showableTypes: "+showableTypes+" purgeEmpyFolders: "+purgeEmpyFolders+" filterCriteria: "+filterCriteria); + + try { + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem folder = workspace.getMySpecialFolders(); + + long startTime = System.currentTimeMillis(); + logger.trace("start time - " + startTime); + + Item itemFolder = ItemBuilder.getItem(null, folder, folder.getPath(), showableTypes, filterCriteria, true); + //OVERRIDING VRE FOLDERS NAME - SET SPECIAL FOLDER /Workspace/MySpecialFolders + itemFolder.setName(WorkspaceExplorerAppConstants.VRE_FOLDERS_LABEL); + itemFolder.setSpecialFolder(true); + + logger.trace("Builded MySpecialFolder: "+itemFolder); + + logger.trace("Only showable types:"); + //printName("", folderItem); + + if (purgeEmpyFolders) { + itemFolder = ItemBuilder.purgeEmptyFolders(itemFolder); + } + + logger.trace("Returning:"); + + Long endTime = System.currentTimeMillis() - startTime; + String time = String.format("%d msc %d sec", endTime, TimeUnit.MILLISECONDS.toSeconds(endTime)); + logger.trace("end time - " + time); + + //printName("", folderItem); + + Collections.sort(itemFolder.getChildren(), new ItemComparator()); + + return itemFolder; + + } catch (Exception e) { + logger.error("Error during special folders retrieving", e); + throw new WorkspaceNavigatorServiceException("Sorry, an error occurred when performing get My Special Folder"); + } + } + + + /** + * {@inheritDoc} + */ + @Override + public boolean checkName(String name) throws WorkspaceNavigatorServiceException { + logger.trace("checkName name: "+name); + try { + ASLSession session = WsUtil.getASLSession(this.getThreadLocalRequest().getSession()); + Workspace workspace = HomeLibrary.getUserWorkspace(session.getUsername()); + return workspace.isValidName(name); + } catch (Exception e) { + logger.error("Error during folder retrieving", e); + throw new WorkspaceNavigatorServiceException(e.getMessage()); + } + } + + /*protected void printName(String indentation, Item item) + { + if(item!=null){ + _log.trace(indentation+item.getName()); + for (Item child:item.getChildren()) printName(indentation+"\t", child); + } + }*/ + + /** + * Gets Breadcrumbs (the list of parents) by item identifier. + * + * @param itemIdentifier the item identifier + * @param includeItemAsParent - if parameter is true and item passed in input is a folder, the folder is included in path returned as last parent + * @return the list parents by item identifier + * @throws Exception the exception + */ + @Override + public List getBreadcrumbsByItemIdentifier(String itemIdentifier, boolean includeItemAsParent) throws Exception { + logger.trace("ListParents By Item Identifier "+ itemIdentifier); + try { + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem wsItem = workspace.getItem(itemIdentifier); + logger.trace("workspace retrieve item name: "+wsItem.getName()); + List parents = workspace.getParentsById(itemIdentifier); + logger.trace("parents size: "+parents.size()); + Item[] arrayParents; + + if(includeItemAsParent==true && wsItem.isFolder()){ + arrayParents = new Item[parents.size()]; + arrayParents[parents.size()-1] = ItemBuilder.buildFolderForBreadcrumbs((WorkspaceFolder) wsItem, null); + } + else { + arrayParents = new Item[parents.size()-1]; + } + + /** HANDLE MY_SPECIAL_FOLDER TO AVOID COMPLETE PATH WORKSPACE/MY_SPECIAL_FOLDER + * BUT RETURNING ONLY /MY_SPECIAL_FOLDER + */ + if(wsItem.isFolder()){ + if(ItemBuilder.isSpecialFolder((WorkspaceFolder) wsItem)){ + return new ArrayList(Arrays.asList(arrayParents)); + } + } + + //CONVERTING PATH + logger.trace("converting path from second-last.."); + for (int i = parents.size()-2; i >= 0; i--) { + WorkspaceFolder wsParentFolder = (WorkspaceFolder) parents.get(i); + arrayParents[i] = ItemBuilder.buildFolderForBreadcrumbs(wsParentFolder, null); + if(arrayParents[i].isSpecialFolder()){ //SKIP HOME PARENT FOR MY_SPECIAL_FOLDER + logger.info("arrayParents index "+i+" is special folder, exit"); + break; + } + } + + //SET PARENTS + logger.trace("setting parents.."); + for(int i=0; i breadcrumbs = new ArrayList(arrayParents.length-1); + for (int i=1; i(Arrays.asList(arrayParents)); + } + + } catch (Exception e) { + logger.error("Error in get List Parents By Item Identifier ", e); + throw new Exception("Sorry, an error occurred during path retrieving!"); + } + } + + /** + * Gets the parents by item identifier to limit. + * + * @param itemIdentifier the item identifier + * @param parentLimit the parent limit + * @param includeItemAsParent the include item as parent + * @return the parents by item identifier to limit + * @throws Exception the exception + */ + @Override + public List getBreadcrumbsByItemIdentifierToParentLimit(String itemIdentifier, String parentLimit, boolean includeItemAsParent) throws Exception { + logger.trace("getBreadcrumbsByItemIdentifierToParentLimit by Item Identifier " + itemIdentifier +" and limit: "+parentLimit); + try { + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem wsItem = workspace.getItem(itemIdentifier); + logger.trace("workspace retrieve item name: "+wsItem.getName()); + List parents = workspace.getParentsById(itemIdentifier); + logger.trace("parents size: "+parents.size()); + Item[] arrayParents; + + if(includeItemAsParent==true && wsItem.isFolder()){ + arrayParents = new Item[parents.size()]; + arrayParents[parents.size()-1] = ItemBuilder.buildFolderForBreadcrumbs((WorkspaceFolder) wsItem, null); + } + else { + arrayParents = new Item[parents.size()-1]; + } + + parentLimit = parentLimit!=null?parentLimit:""; + + /** HANDLE MY_SPECIAL_FOLDER TO AVOID COMPLETE PATH WORKSPACE/MY_SPECIAL_FOLDER + * BUT RETURNING ONLY /MY_SPECIAL_FOLDER + */ + if(wsItem.isFolder()){ + if(ItemBuilder.isSpecialFolder((WorkspaceFolder) wsItem)){ + logger.debug("item id is special folder, returning"); + return new ArrayList(Arrays.asList(arrayParents)); + } + + if(itemIdentifier.compareTo(parentLimit)==0){ + logger.debug("item and parent limit are identical element, returning"); + return new ArrayList(Arrays.asList(arrayParents)); + } + + } + + //CONVERTING PATH + logger.trace("converting path from second-last.."); + for (int i = parents.size()-2; i >= 0; i--) { + WorkspaceFolder wsParentFolder = (WorkspaceFolder) parents.get(i); + arrayParents[i] = ItemBuilder.buildFolderForBreadcrumbs(wsParentFolder, null); + if(arrayParents[i].isSpecialFolder()){ //SKIP HOME PARENT FOR MY_SPECIAL_FOLDER + logger.info("arrayParents index "+i+" is special folder, break"); + break; + }else if(parentLimit.compareTo(arrayParents[i].getId())==0){ + logger.info("reached parent limit "+parentLimit+", break"); + break; + } + } + + //SET PARENTS + logger.trace("setting parents.."); + for(int i=0; i breadcrumbs = new ArrayList(); + for (int i=1; i(Arrays.asList(arrayParents)); + } + + } catch (Exception e) { + logger.error("Error in get List Parents By Item Identifier ", e); + throw new Exception("Sorry, an error occurred during path retrieving!"); + } + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.rpc.WorkspaceExplorerService#loadSizeByItemId(java.lang.String) + */ + @Override + public Long getSizeByItemId(String itemId) throws Exception { + + logger.info("get Size By ItemId "+ itemId); + try { + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem wsItem = workspace.getItem(itemId); + Long size = new Long(-1); + + if(wsItem instanceof FolderItem){ //ITEM + FolderItem folderItem = (FolderItem) wsItem; + size = new Long(folderItem.getLength()); + } else if (wsItem instanceof WorkspaceFolder ){ //FOLDER + WorkspaceFolder theFolder = (WorkspaceFolder) wsItem; + size = theFolder.getSize(); + } else if (wsItem instanceof WorkspaceSharedFolder){ //SHARED FOLDER + WorkspaceSharedFolder theFolder = (WorkspaceSharedFolder) wsItem; + size = theFolder.getSize(); + } + logger.info("returning size: " +size); + return size; + + } catch (Exception e) { + logger.error("get Size By ItemId ", e); + throw new Exception(e.getMessage()); + } + } + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.rpc.WorkspaceExplorerService#getMimeType(java.lang.String) + */ + @Override + public String getMimeType(String itemId) throws Exception { + + logger.info("get MimeType By ItemId "+ itemId); + try { + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem wsItem = workspace.getItem(itemId); + + if(!wsItem.getType().equals(WorkspaceItemType.FOLDER_ITEM)) { + return null; + } + + FolderItem folderItem = (FolderItem) wsItem; + + return folderItem.getMimeType(); + + } catch (Exception e) { + logger.error("get MimeType By ItemId ", e); + throw new Exception(e.getMessage()); + } + } + + + /** + * Gets the user acl for folder id. + * + * @param folderId the folder id + * @return the user acl for folder id + * @throws Exception the exception + */ + @Override + public String getUserACLForFolderId(String folderId) throws Exception{ + try { + logger.info("Get user ACL to FOLDER id: "+folderId); + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem wsItem = workspace.getItem(folderId); + + if(!isASharedFolder(wsItem, false)) { + return "OWNER"; + } + else { + return wsItem.getACLUser().toString(); + } + } catch (Exception e) { + logger.error("Error in server get UserACLForFolderId", e); + String error = "An error occurred when getting ACL rules for selected folder. "+e.getMessage(); + throw new Exception(error); + } + } + + + /** + * Checks if is a shared folder. + * + * @param item the item + * @param asRoot the as root + * @return true, if is a shared folder + */ + private boolean isASharedFolder(WorkspaceItem item, boolean asRoot){ + try { + + if(item!=null && item.isFolder() && item.isShared()){ //IS A SHARED SUB-FOLDER + if(asRoot) + { + return item.getType().equals(WorkspaceItemType.SHARED_FOLDER); //IS ROOT? + } + + return true; + } + return false; + }catch(Exception e){ + logger.error("Error in server isASharedFolder", e); + return false; + } + } + + + /* (non-Javadoc) + * @see org.gcube.portlets.widgets.wsexplorer.client.rpc.WorkspaceExplorerService#getFormattedSizeByItemId(java.lang.String, org.gcube.portlets.widgets.wsexplorer.shared.SizeFormatter) + */ + @Override + public String getReadableSizeByItemId(String itemId) throws Exception { + + try{ + logger.info("getFormattedSize ByItemId "+ itemId); + long size = getSizeByItemId(itemId); + return StringUtil.readableFileSize(size); + } catch (Exception e) { + logger.error("getFormattedSize By ItemId ", e); + throw new Exception(e.getMessage()); + } + } + + /* (non-Javadoc) + * @see org.gcube.portlets.user.workspaceexplorerapp.client.rpc.WorkspaceExplorerAppService#createFolder(java.lang.String, java.lang.String, java.lang.String) + */ + @Override + public Item createFolder(String nameFolder, String description, String parentId) throws Exception { + + logger.debug("creating folder: "+nameFolder +", parent id: "+parentId); + + try { + + if(parentId==null || parentId.isEmpty()) + throw new Exception("Parent id is null or empty"); + + if(nameFolder == null) + nameFolder = "Empty Folder"; + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceFolder wsFolder = workspace.createFolder(nameFolder, description, parentId); + List allTypes = Arrays.asList(ItemType.values()); + + Item parent = null; + try{ + String parentPath = wsFolder.getParent()!=null?wsFolder.getParent().getPath():""; + parent = ItemBuilder.getItem(null, wsFolder.getParent(), parentPath, allTypes, null, false); + }catch(Exception e){ + logger.error("Get parent thown an exception, is it the root id? "+parentId); + } + + //TODO PATCH TO AVOID PROBLEM ON GETPATH. FOR EXAMPLE WHEN PARENT IS ROOT + String itemPath = null; + try{ + itemPath = wsFolder.getPath(); + }catch(Exception e){ + logger.error("Get path thown an exception, for id: "+wsFolder.getId()); + itemPath= wsFolder.isFolder()?workspace.getRoot().getPath()+"/"+wsFolder.getName():workspace.getRoot().getPath(); + } + + return ItemBuilder.getItem(parent, wsFolder, itemPath, allTypes, null, false); + + } catch(InsufficientPrivilegesException e){ + String error = "Insufficient Privileges to create the folder"; + logger.error(error, e); + throw new Exception(error); + } catch (ItemAlreadyExistException e) { + String error = "An error occurred on creating folder, " +e.getMessage(); + logger.error(error, e); + throw new Exception(error); + } catch (Exception e) { + String error = "An error occurred on the sever during creating folder. Try again"; + logger.error(error, e); + throw new Exception(error); + } + + } + + + /** + * Gets the public link for item id. + * + * @param itemId the item id + * @return the public link for item id + * @throws Exception the exception + */ + @Override + public String getPublicLinkForItemId(String itemId) throws Exception{ + + logger.trace("get Public Link For ItemId: "+ itemId); + try{ + + if(itemId==null) + throw new Exception("Sorry, The Public Link for empty item is unavailable (itemId is null)"); + + Workspace workspace = WsUtil.getWorkspace(this.getThreadLocalRequest().getSession()); + WorkspaceItem wsItem = workspace.getItem(itemId); + + if(wsItem==null) + throw new Exception("Sorry, The Public Link for empty item is unavailable"); + + if(wsItem.getType().equals(WorkspaceItemType.FOLDER_ITEM)){ + + FolderItem folderItem = (FolderItem) wsItem; + String uriRequest = folderItem.getPublicLink(false); + + if(uriRequest==null || uriRequest.isEmpty()) + throw new Exception("Sorry, public link on "+folderItem.getName() +" is not available"); + + return uriRequest; + + }else{ + logger.warn("ItemId: "+ itemId +" is not available, sent exception Public Link unavailable"); + throw new Exception("Sorry, The Public Link for selected item is unavailable"); + } + + }catch (Exception e) { + logger.error("Error getPublicLinkForItemId for item: "+itemId, e); + throw new Exception(e.getMessage()); + } + + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WsUtil.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WsUtil.java new file mode 100644 index 0000000..b154e9a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/server/WsUtil.java @@ -0,0 +1,89 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.server; + +import javax.servlet.http.HttpSession; + +import org.gcube.application.framework.core.session.ASLSession; +import org.gcube.application.framework.core.session.SessionManager; +import org.gcube.common.homelibrary.home.HomeLibrary; +import org.gcube.common.homelibrary.home.exceptions.HomeNotFoundException; +import org.gcube.common.homelibrary.home.exceptions.InternalErrorException; +import org.gcube.common.homelibrary.home.workspace.Workspace; +import org.gcube.common.homelibrary.home.workspace.exceptions.WorkspaceFolderNotFoundException; +import org.gcube.common.scope.api.ScopeProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +/** + * The Class WsUtil. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 7, 2016 + */ +public class WsUtil { + + public static final String USERNAME_ATTRIBUTE = "username"; + public static final String TEST_USER = "francesco.mangiacrapa"; + public static final String TEST_SCOPE = "/gcube/devsec/devVRE"; + + public static final Logger logger = LoggerFactory.getLogger(WsUtil.class); + + /** + * Gets the ASL session. + * + * @param httpSession the http session + * @return the ASL session + */ + public static ASLSession getASLSession(HttpSession httpSession) { + String sessionID = httpSession.getId(); + String user = (String) httpSession.getAttribute(USERNAME_ATTRIBUTE); + + //TODO we check for the older attribute name + if (user == null) { + user = (String) httpSession.getAttribute("user"); + } + + if (user == null) { + + logger.error("WORKSPACE PORTLET STARTING IN TEST MODE - NO USER FOUND"); + + //for test only +// user = "test.user"; + user = TEST_USER; + httpSession.setAttribute(USERNAME_ATTRIBUTE, user); + ASLSession session = SessionManager.getInstance().getASLSession(sessionID, user); + session.setScope(TEST_SCOPE); + + return session; + } + else { + logger.trace("user found in session "+user); + } + return SessionManager.getInstance().getASLSession(sessionID, user); + } + + /** + * Gets the workspace. + * + * @param httpSession the http session + * @return the workspace + * @throws InternalErrorException the internal error exception + * @throws HomeNotFoundException the home not found exception + * @throws WorkspaceFolderNotFoundException the workspace folder not found exception + */ + public static Workspace getWorkspace(HttpSession httpSession) throws InternalErrorException, HomeNotFoundException, WorkspaceFolderNotFoundException { + ASLSession session = getASLSession(httpSession); + logger.trace("Scope : "+session.getScope() + " username: "+session.getUsername()); + String scope = session.getScope(); + if(scope==null) + scope= WsUtil.TEST_SCOPE; + System.out.println("Scope : "+scope + " username: "+session.getUsername()); + ScopeProvider.instance.set(scope); + Workspace workspace = HomeLibrary.getUserWorkspace(session.getUsername()); + return workspace; + } + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/FilterCriteria.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/FilterCriteria.java new file mode 100644 index 0000000..be91461 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/FilterCriteria.java @@ -0,0 +1,116 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + + +/** + * The Class FilterCriteria. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 18, 2015 + */ +public class FilterCriteria implements Serializable { + + + private static final long serialVersionUID = 1912760277441333686L; + protected List allowedMimeTypes; + protected Map requiredProperties; + protected List allowedFileExtensions; + + /** + * Instantiates a new filter criteria. + */ + public FilterCriteria(){} + + + /** + * Instantiates a new filter criteria. + * + * @param allowedMimeTypes the allowed mime types + * @param allowedFileExtensions the allowed file extensions + * @param requiredProperties the required properties + */ + public FilterCriteria(List allowedMimeTypes, List allowedFileExtensions, Map requiredProperties) { + this.allowedMimeTypes = allowedMimeTypes; + this.allowedFileExtensions = allowedFileExtensions; + this.requiredProperties = requiredProperties; + } + + /** + * Sets the allowed mime types. + * + * @param allowedMimeTypes the allowedMimeTypes to set + */ + public void setAllowedMimeTypes(List allowedMimeTypes) { + this.allowedMimeTypes = allowedMimeTypes; + } + + + /** + * Sets the required properties. + * + * @param requiredProperties the requiredProperties to set + */ + public void setRequiredProperties(Map requiredProperties) { + this.requiredProperties = requiredProperties; + } + + + /** + * Sets the allowed file extensions. + * + * @param allowedFileExtensions the allowedFileExtensions to set + */ + public void setAllowedFileExtensions(List allowedFileExtensions) { + this.allowedFileExtensions = allowedFileExtensions; + } + + /** + * Gets the allowed file extensions. + * + * @return the allowed file extensions + */ + public List getAllowedFileExtensions() { + return allowedFileExtensions; + } + + /** + * Gets the allowed mime types. + * + * @return the allowedMimeTypes + */ + public List getAllowedMimeTypes() { + return allowedMimeTypes; + } + + /** + * Gets the required properties. + * + * @return the requiredProperties + */ + public Map getRequiredProperties() { + return requiredProperties; + } + + + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("FilterCriteria [allowedMimeTypes="); + builder.append(allowedMimeTypes); + builder.append(", requiredProperties="); + builder.append(requiredProperties); + builder.append(", allowedFileExtensions="); + builder.append(allowedFileExtensions); + builder.append("]"); + return builder.toString(); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/HandlerResultMessage.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/HandlerResultMessage.java new file mode 100644 index 0000000..c09c132 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/HandlerResultMessage.java @@ -0,0 +1,153 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + +import java.io.Serializable; + + +/** + * The Class HandlerResultMessage. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 7, 2016 + */ +public class HandlerResultMessage implements Serializable{ + + /** + * + */ + private static final long serialVersionUID = -817188198850449565L; + + /** + * The Enum Status. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Mar 7, 2016 + */ + public enum Status { + /** + * If an error occurs. + */ + ERROR, + /** + * If no error occurs. + */ + OK, + /** + * If there was some problems. + */ + WARN, + + /** + * If the result is unknown. + */ + UNKNOWN; + } + + /** + * Error result. + * + * @param message the message + * @return the handler result message + */ + public static HandlerResultMessage errorResult(String message){ + return new HandlerResultMessage(Status.ERROR, message); + } + + /** + * Ok result. + * + * @param message the message + * @return the handler result message + */ + public static HandlerResultMessage okResult(String message){ + return new HandlerResultMessage(Status.OK, message); + } + + /** + * Warn result. + * + * @param message the message + * @return the handler result message + */ + public static HandlerResultMessage warnResult(String message){ + return new HandlerResultMessage(Status.WARN, message); + } + + /** + * Parses the result. + * + * @param result the result + * @return the handler result message + */ + public static HandlerResultMessage parseResult(String result){ + //expected 200:Upload complete + String statusToken = null; + String messageToken = null; + + int index = result.indexOf(':'); + if (index>0){ + statusToken = result.substring(0,index); + if (index children; + private String owner; + private boolean isFolder; + private boolean isSpecialFolder = false; + private boolean isSharedFolder = false; + private boolean isRoot = false; + private Date creationDate; + + /** + * Instantiates a new item. + */ + public Item() { + } + /** + * Instantiates a new item. + * + * @param id the id + * @param name the name + * @param isFolder the is folder + */ + public Item(String id, String name, boolean isFolder) { + this.id = id; + this.isFolder = isFolder; + this.name = name; + } + + /** + * Instantiates a new item. + * + * @param parent the parent + * @param id the id + * @param name the name + * @param type the type + * @param path the path + * @param owner the owner + * @param date the creationDate + * @param isFolder the is folder + * @param isRoot the is root + */ + public Item(Item parent, String id, String name, ItemType type, String path, String owner, Date creationDate, boolean isFolder, boolean isRoot) { + this(id, name, isFolder); + this.parent = parent; + this.type = type; + this.path = path; + this.children = new ArrayList(); + this.owner = owner; + this.creationDate = creationDate; + this.isRoot = isRoot; + } + + + /** + * @return the creationDate + */ + public Date getCreationDate() { + + return creationDate; + } + + /** + * @param creationDate the creationDate to set + */ + public void setCreationDate(Date creationDate) { + + this.creationDate = creationDate; + } + /** + * Sets the id. + * + * @param id the id to set + */ + public void setId(String id) { + this.id = id; + } + + /** + * Checks if is root. + * + * @return true, if is root + */ + public boolean isRoot() { + return isRoot; + } + + /** + * Sets the is root. + * + * @param isRoot the is root + * @return true, if successful + */ + public void setIsRoot(boolean isRoot) { + this.isRoot = isRoot; + } + + /** + * Checks if is folder. + * + * @return the isFolder + */ + public boolean isFolder() { + return isFolder; + } + + /** + * Sets the folder. + * + * @param isFolder + * the isFolder to set + */ + public void setFolder(boolean isFolder) { + this.isFolder = isFolder; + } + + /** + * Checks if is shared folder. + * + * @return the isSharedFolder + */ + public boolean isSharedFolder() { + return isSharedFolder; + } + + /** + * Sets the shared folder. + * + * @param isSharedFolder + * the isSharedFolder to set + */ + public void setSharedFolder(boolean isSharedFolder) { + this.isSharedFolder = isSharedFolder; + } + + /** + * The item parent. Null if is the root. + * + * @return the item parent. + */ + public Item getParent() { + return parent; + } + + /** + * The item id. + * + * @return the id. + */ + public String getId() { + return id; + } + + /** + * The item name. + * + * @return the name. + */ + public String getName() { + return name; + } + + /** + * The item type. + * + * @return the type. + */ + public ItemType getType() { + return type; + } + + /** + * The item children. + * + * @return the children. + */ + public ArrayList getChildren() { + return children; + } + + /** + * Gets the owner. + * + * @return the owner + */ + public String getOwner() { + return owner; + } + + /** + * Sets the name. + * + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * Sets the owner. + * + * @param owner + * the owner to set + */ + public void setOwner(String owner) { + this.owner = owner; + } + + /** + * The item child. + * + * @param index + * the index + * @return the child at the specific position. + */ + public Item getChild(int index) { + return children.get(index); + } + + /** + * Add a child to this item. + * + * @param child + * the child to add. + */ + public void addChild(Item child) { + children.add(child); + } + + /** + * Remove a child from this item. + * + * @param child + * the child + */ + public void removeChild(Item child) { + children.remove(child); + } + + /** + * Checks if is special folder. + * + * @return the isSpecialFolder + */ + public boolean isSpecialFolder() { + return isSpecialFolder; + } + + /** + * Sets the special folder. + * + * @param isSpecialFolder the isSpecialFolder to set + */ + public void setSpecialFolder(boolean isSpecialFolder) { + this.isSpecialFolder = isSpecialFolder; + } + + /** + * Gets the path. + * + * @return the path + */ + public String getPath() { + return path; + } + + /** + * {@inheritDoc} + */ + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (id == null ? 0 : id.hashCode()); + return result; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + Item other = (Item) obj; + if (id == null) { + if (other.id != null) { + return false; + } + } else if (!id.equals(other.id)) { + return false; + } + return true; + } + + /** + * Sets the parent. + * + * @param parent + * the new parent + */ + public void setParent(Item parent) { + this.parent = parent; + } + /* (non-Javadoc) + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + + StringBuilder builder = new StringBuilder(); + builder.append("Item [id="); + builder.append(id); + builder.append(", name="); + builder.append(name); + builder.append(", type="); + builder.append(type); + builder.append(", path="); + builder.append(path); + builder.append(", children="); + builder.append(children); + builder.append(", owner="); + builder.append(owner); + builder.append(", isFolder="); + builder.append(isFolder); + builder.append(", isSpecialFolder="); + builder.append(isSpecialFolder); + builder.append(", isSharedFolder="); + builder.append(isSharedFolder); + builder.append(", isRoot="); + builder.append(isRoot); + builder.append(", creationDate="); + builder.append(creationDate); + builder.append("]"); + return builder.toString(); + } + + +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemCategory.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemCategory.java new file mode 100644 index 0000000..b1b7cce --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemCategory.java @@ -0,0 +1,17 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + + +/** + * The Enum ItemCategory. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 30, 2015 + */ +public enum ItemCategory { + + HOME, + VRE_FOLDER; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemInterface.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemInterface.java new file mode 100644 index 0000000..243ce06 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemInterface.java @@ -0,0 +1,28 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + + +/** + * The Interface IntemInterface. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 22, 2016 + */ +public interface ItemInterface { + + /** + * Gets the parent. + * + * @return the parent + */ + ItemInterface getParent(); + + /** + * Gets the id. + * + * @return the id + */ + String getId(); +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemType.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemType.java new file mode 100644 index 0000000..e71f6b7 --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/ItemType.java @@ -0,0 +1,31 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + + +/** + * The Enum ItemType. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 18, 2015 + */ +public enum ItemType { + + FOLDER, //MANDATORY + EXTERNAL_IMAGE, + EXTERNAL_FILE, + EXTERNAL_PDF_FILE, + EXTERNAL_URL, + QUERY, + REPORT_TEMPLATE, + REPORT, + DOCUMENT, + METADATA, + PDF_DOCUMENT, + IMAGE_DOCUMENT, + URL_DOCUMENT, + GCUBE_ITEM, + TIME_SERIES, + UNKNOWN_TYPE; +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/PublicLink.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/PublicLink.java new file mode 100644 index 0000000..74a91be --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/PublicLink.java @@ -0,0 +1,94 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + +import java.io.Serializable; + + +/** + * The Class PublicLink. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 23, 2016 + */ +public class PublicLink implements Serializable { + + /** + * + */ + private static final long serialVersionUID = 4050358438512028240L; + private String completeURL; + private String shortURL; + + /** + * Instantiates a new public link. + */ + public PublicLink() { + + } + + /** + * Instantiates a new public link. + * + * @param completeURL the complete url + * @param shortURL the short url + */ + public PublicLink(String completeURL, String shortURL) { + super(); + this.completeURL = completeURL; + this.shortURL = shortURL; + } + + /** + * Gets the complete url. + * + * @return the completeURL + */ + public String getCompleteURL() { + return completeURL; + } + + /** + * Gets the short url. + * + * @return the shortURL + */ + public String getShortURL() { + return shortURL; + } + + /** + * Sets the complete url. + * + * @param completeURL the completeURL to set + */ + public void setCompleteURL(String completeURL) { + this.completeURL = completeURL; + } + + /** + * Sets the short url. + * + * @param shortURL the shortURL to set + */ + public void setShortURL(String shortURL) { + this.shortURL = shortURL; + } + + /* + * (non-Javadoc) + * + * @see java.lang.Object#toString() + */ + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("PublicLink [completeURL="); + builder.append(completeURL); + builder.append(", shortURL="); + builder.append(shortURL); + builder.append("]"); + return builder.toString(); + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/SizeFormatter.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/SizeFormatter.java new file mode 100644 index 0000000..8e91f8a --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/SizeFormatter.java @@ -0,0 +1,49 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + + +/** + * The Enum SizeFormatter. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Feb 22, 2016 + */ +public enum SizeFormatter { + + KB("KB", 1024), + MB("MB", 1048576); + + private long value; + private String unit; + + /** + * Instantiates a new size formatter. + * + * @param unit the unit + * @param value the value + */ + private SizeFormatter(String unit, long value) { + this.unit = unit; + this.value = value; + } + + /** + * Gets the value. + * + * @return the value + */ + public long getValue() { + return value; + } + + /** + * Gets the unit. + * + * @return the unit + */ + public String getUnit() { + return unit; + } +} diff --git a/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/WorkspaceNavigatorServiceException.java b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/WorkspaceNavigatorServiceException.java new file mode 100644 index 0000000..7ba8e2d --- /dev/null +++ b/src/main/java/org/gcube/portlets/user/workspaceexplorerapp/shared/WorkspaceNavigatorServiceException.java @@ -0,0 +1,35 @@ +/** + * + */ +package org.gcube.portlets.user.workspaceexplorerapp.shared; + + +/** + * The Class WorkspaceNavigatorServiceException. + * + * @author Francesco Mangiacrapa francesco.mangiacrapa@isti.cnr.it + * Jun 18, 2015 + */ +public class WorkspaceNavigatorServiceException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 6416932531764081333L; + + /** + * Instantiates a new workspace navigator service exception. + */ + public WorkspaceNavigatorServiceException() { + } + + /** + * Instantiates a new workspace navigator service exception. + * + * @param message the message + */ + public WorkspaceNavigatorServiceException(String message) { + super(message); + } + +} diff --git a/src/main/resources/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml b/src/main/resources/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml new file mode 100644 index 0000000..cfc709d --- /dev/null +++ b/src/main/resources/org/gcube/portlets/user/workspaceexplorerapp/WorkspaceExplorerApp.gwt.xml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000..74c8c9c --- /dev/null +++ b/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,31 @@ + + + + WorkspaceExplorerApp.html + + + workspaceExplorerAppServlet + org.gcube.portlets.user.workspaceexplorerapp.server.WorkspaceExplorerAppServiceImpl + + + DownloadServlet + org.gcube.portlets.user.workspaceexplorerapp.server.DownloadWorkspaceExplorerServlet + + + workspaceExplorerAppServlet + /workspaceexplorerapp/WorkspaceExplorerAppService + + + DownloadServlet + /workspaceexplorerapp/DownloadServlet + + + workspace-explorer-app + + + WorkspaceExplorerApp.html + + \ No newline at end of file diff --git a/src/main/webapp/WorkspaceExplorerApp.css b/src/main/webapp/WorkspaceExplorerApp.css new file mode 100644 index 0000000..e068e2b --- /dev/null +++ b/src/main/webapp/WorkspaceExplorerApp.css @@ -0,0 +1,209 @@ +/* TEMPLATE START*/ +html, body { + height: 100%; +} + +#wrap_we { + min-height: 100%; +} + +#header_we { + height: 90px; + background: linear-gradient(to bottom, #FFFFFF, #F5F5F5); + border-bottom: 2px solid #8F8F8F; +} + +#content_we { + /* overflow: auto; */ + overflow: hidden; + padding-bottom: 50px; /* must be same height as the footer */ +} + +#footer_we { + position: relative; + margin-top: -50px; /* negative value of footer height */ + height: 50px; + clear: both; + /* background-color: #7F7F7F; */ + background: url("img/dark-noise.png") repeat scroll 0 0 #2196F3; + width: 100%; + text-align: center; + vertical-align: middle; + line-height: 50px; +} + +/*Opera Fix*/ +body:before { + content: ""; + height: 100%; + float: left; + width: 0; + margin-top: -32767px; +} + +#links-footer { + /* vertical-align: middle; + height: 100%; */ + color: #FFFFFF; + font-family: serif; + font-size: 13px; +} + +#links-footer a { + color: #FFF; + text-decoration: underline; + /* font-weight: bold; */ +} + +#links-footer a:HOVER { + /* text-decoration: underline; */ + +} + +#WorkspaceExplorerAppPanel>table td { + opacity: 1 !important; +} + +#WorkspaceExplorerAppPanel>table th { + opacity: 1 !important; +} + +/********************/ +/*WORKSPACE EXPLORER*/ +.navigation_explorer_app { + padding-top: 48px; + height: 100%; + /* margin-right: 2px; */ + text-align: center; + /* border-right: 1px solid #8F8F8F; */ +} + +.table-overflow td, th { + overflow: hidden !important; + height: 100%; +} + +.table-overflow th:FIRST-CHILD { + width: 20px !important; +} + +.table-overflow tr:FIRST-CHILD { + width: 20px !important; +} + +#workspaceEplorerApplicationDiv { + width: 100%; + height: 100%; +} + +.view_items_explorer_app { + margin-top: 2px; +} + +.workspace-explorer-container :FIRST-CHILD td { + padding-top: 0px !important; + padding-bottom: 0px !important; +} + +.navigation_link li:HOVER { + /*background-color: transparent !important;*/ + text-decoration: underline !important; + color: #2196F3; +} + +.navigation_link .side-nav li.active { + background-color: transparent !important; +} + +/********************/ +.breadcrumbs-we { + /* font-size: 13px; */ + list-style: none outside none; + margin-bottom: 3px; + margin-left: 2px; + margin-top: 3px; + padding: 10px !important; + background-color: #F5F5F5; + border-radius: 4px; + font-size: 14px; +} + +.breadcrumbs-we li { + display: inline-block; +} + +.breadcrumbs-we .active { + color: #999999; + text-decoration: none; +} + +.breadcrumbs-we .divider { + color: #AABBCC; + padding: 0 3px; + background-color: transparent !important; +} + +.breadcrumbs-we a { + color: #226599; + text-decoration: none; +} + +.breadcrumbs-we a:hover { + text-decoration: underline; +} + +/*PADDING FOR TABLE (COLUMNS) OF CONTENTS (WORKSPACE ITEMS)*/ +#explorer_panel_we td { + padding-top: 15px !important; + padding-bottom: 15px !important; +} + +.context-menu-we { + -webkit-border-bottom-right-radius: 5px; + -webkit-border-bottom-left-radius: 5px; + -moz-border-radius-bottomright: 5px; + -moz-border-radius-bottomleft: 5px; + border-bottom-right-radius: 5px; + border-bottom-left-radius: 5px; + border: 1px solid #D1D1D1; + background-color: white; +} + +.context-menu-we .row { + margin: 0 !important; + /* background-color: #B5C5DF; */ + padding-bottom: 3px; + padding-left: 5px; + padding-right: 5px; +} + +#data_grid_explorer td { + font-size: 15px !important; +} + +.dataGridSelectedRow { + background: none repeat scroll 0 0 #A9C1EB !important; + color: #FFFFFF !important; + height: auto !important; + overflow: auto !important; +} + +.navigation-cursor { + cursor: url(img/glass_cursor.cur), auto; +} + +.popup-order { + border: 1px solid #D1D1D1; + background-color: white; +} + +.popup-order .row { + margin: 0 !important; + padding-bottom: 3px; + padding-left: 5px; + padding-right: 5px; +} + +.under-line-onhover :HOVER { + text-decoration: underline; +} \ No newline at end of file diff --git a/src/main/webapp/WorkspaceExplorerApp.html b/src/main/webapp/WorkspaceExplorerApp.html new file mode 100644 index 0000000..d825154 --- /dev/null +++ b/src/main/webapp/WorkspaceExplorerApp.html @@ -0,0 +1,46 @@ + + + + + + +Welcome - gCube Folder Explorer Application + + + + + + +
+ + + + + + +
+
+
+ +
+ + + + + + diff --git a/src/main/webapp/WorkspaceExplorerAppMaterial.html b/src/main/webapp/WorkspaceExplorerAppMaterial.html new file mode 100644 index 0000000..fab510c --- /dev/null +++ b/src/main/webapp/WorkspaceExplorerAppMaterial.html @@ -0,0 +1,25 @@ + + + + + +Welcome - gCube Folder Explorer Application + + + + + + + +
+ + + + diff --git a/src/main/webapp/error404.html b/src/main/webapp/error404.html new file mode 100644 index 0000000..2ba1a62 --- /dev/null +++ b/src/main/webapp/error404.html @@ -0,0 +1,26 @@ + + + + + +Error 404 - gCube Folder Explorer Application + + + + +
+ D4Science Workspace Folder Explorer
+

404 NOT FOUND

+
+

Sorry, the request resource is not found!

+
+ + + + diff --git a/src/main/webapp/img/d4science_workspace_logo.png b/src/main/webapp/img/d4science_workspace_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..71063dba763c3d03031d8ebe075a94061b252267 GIT binary patch literal 105770 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 z z0Vh!)unq^}aaB)Wayao=Usu(pV{8%>alUZond@T@{PCf$Z++^i?~qGIDL~6Ymb7Oy zok?@#-$vV?x_f#!2kc-p4W-X?Cev0e3ItGP;40CY`!B7A(o~fe4JaK=QwbDlN=o!; zuPC{nkUI#=kFk%AGE#6x*^-}LeDS93b5oz^37U&YIj?ER2BM-={N}+btq1K0<8S(x z!wu?T`EP3fxwB3@E$}~xN~87B;5L&u>3h5^@aL!ZtPR3pcHbh{spe=nog3NxUh2U%aujDvUEIFR30H8OX%3fRd`b zu1?pt#xKKJJZhMj#LGNtzu?H zr~NAT45+ofjn&PIKGNKcri&Tf=1{(%$qt#bTG|7SuFjAk?2&UcO2!My7sFU4;f4`A0orSG8*`RKQNq2P;aWIyE2`8eGYw7Ro=K z43RP3RvRh61CJwtygIB$nz8^90qA-*NC4)NXbvS(8Sj zPUWT1I}Mx-bv`0IF-7Xcua>V^{-fP5?|uv3d2kT{466;U{H+$Y%ckAM2&t-Mp z5MbCu<_RPLuv5s7j^XHEIK1+-ClK**pC&1xkF+fkDun>vnLb=!=aW57kyMP5I734+ zhGijh$6+60X(_6BY-JYz3dvQ-;yh9E^B%Vb$Qj_HBe8 z7aMuQ?^~2LmV||9pD6|dqEy))9QAy#ZDiz@eJvblNWUAcjBKvn=x_7wlk#d3?N*0?jE&~?R8f=u>DEu# zncx0e2nT#pUZADp83AKFbM!5mA}`%?>nElB6Zbd*ZjYQnQ?r;<2;@w|w{$<%KM6 zbm$MxP}FT_Wh3SBsKZe2We725jI`HR8_;+z{i#oUs+fE5E-~ow%2@$6f|>mWuRmiv zD8l+#_}HzVlBMlibf3$uAT8DS)ek2rgFMM#XHb_bg*2xa>WonzgS-HDG4N(aASDmV zo-3DBq0E^sXlLp_eCVT-n(p+-ll1)V+UG_JyKWiE?R>E*w1zf-o>ahewD`mmPk!vt z#~*(j4G>`(7b_WUZ356ifO~p+xy4I5*%l|-V@lvNJy3LD_bCVB1L?Q~W)_TMWR4_e zlz1BF0hGABQ9RxIxCjK~NAVXm0xFV3MKKXq zBvDXMM2(u5=Ykry1dY+?dx^$n+(BcEBC^adYtPct)BC>vzwdV6p}Xl>Ks0$t7u>nG zt4>v&I=AZFQ*}<&IX-r6um)&ElgpY1*C@oWT67NeEK`hT1{7u4`N4zXKPVRMbA}9N zXRr#AjK%8}JPsdt@t~Q^s7k1(7bQ=F#XKdv&!eQY!ZJ~}L|IoDhFu!WKk+7NGy&iD zO1mvSe?Q0(9#?OuazER5s%M8wPmLf9ld-4=ZSWuaYR5z)M%qOO{_ZWHxq{rJjN!{E zk2&GF`oWH)wYN`dbju?h*l^xzC@R=jx^dDInhR=92sHa^Fe$(S5n2Gr6YnXS4^c z<8Qvj(RLubVZ2^y`ADO*fb~ul4x+0H{KdX>tWjaCtTbAJlZ!qYu=wq5?M~<3c9$@i zj|6R4Z3>Tr+eE|K(Y6VYGQ)vBNX<=Xgg)p!xun|>3|K3JaxXZ9@TR%MQ!uwQYPfl( z!{_lkAgFK;GY=Su!l9Ahj1!FecMg;~ona&5sO%V?u}v&qPGVu}gIyY+Q-!a_e6_A{k6fyk&==%r*l^@+I}hKPT+{3P*-4oaJOob zq_u2yjZHtk@I>zet(CM-BXjA!wYgeVqX|)5r&N{-nT-UT+@y*dH_USRwDEy}2gjpf zi4cpT5lBSd0k7XXVDlQop_n#;BZ1Os#Ll3eQxetRHq+*D`E9BKS)|~v16A&On@gec z7u51HlwG=ZhBI2K^qBiyeVuJ~tH0OCAeGhidrdprxE9Q#GZ0mNyiXNCk zFCdIopiQ+rj4}nSq!dzV@I6~W!5hv--S>+2VW`U#D!EbV3Cm&p&=>udzTX*wvLOH) zF3Lh#j1BJH)#K`mtCeqAjiJ9`eH))xoLFtZ>9IBV5|^Ow(5wXJV51M&uw)l7;E@=w zo9+qKss^HAoWX028vUF0)`oUE<+Nj?X^wtLjlbaJ3NKb|tld2h%YfO@UtLf%fc?hR zV(mg7#+MQ2;;Adf=(LrUTD`aVC8?b35(@^ZN^De?#JF=}m|YJ^F2OQkilfkIR0ZS4 z8FaPvdi|BHFDv9w00~-jxwH%*v-<98yENPpR4a>>A=A=vuhp#_w-J1>`^+?0S1$X%7^yKHEN~0vO=e=sn!{MEicQ-Jn^APsK&uiNdm3+u)8{v zRS5m@8>#;2_S+Qbk81YE`*QThGW17_tFNQYW{p}RedESzDa0pH#9x}pc(n;vm(|;b zW1;$>kl==WDh%S#{_{YG_!!_jb7rX?yATrSSCn3{o_oO2%%Jo}^ePRl)IRCtJAKkk3u_=4@HeW-nry#|p@{^%)p}(ukOwA-V(078_9XMK? z%!%#eKs%fuFgKdRfYGT{1yCU17$k5Co-ESZ+KQu&JkZn@|8dIXNo$5KA0!q&T0=u* zq_B_Uz+RWb-=*zVv|^;%i_S3F_2Z_U;@{FTIns%P4?m$;+f(c_Q9cR<1QSOeivW@9Jm_bq1hsgYt%#jzSm8 zWG&fEcSoo8V}1RRmrc8dS6|wY4P9!`XsXFD(j5!Ddpapd&PsaRVeHGK-A9nU?pE9@+l_l4zjQ>g#k_yq?VB0gZdbu>PHx+<%Ve;H6tYvx`f%cK50-ECY76Clr6WEo*(XT`9Ozl9)z(fh z);3Hs98)nyU0fi6llml?KrLaP=>&WPsBvaT9wZ;~f=wJCBop-&y21vndb~y%n=`hw zV5~x-NK@g*E0BFYtn(?|NkTnAb+9iyIqHs1?&}M5-SNvigV$Vn^`Wkdvsx^03%KDi z*(QBip|)XpS}`=M;;gh5I%I2+}XUUmJ}{oVsqQx+$XvO)Op*Y_Yv@ z&)<6=y=#a0;l=3?vZyTuz&JpU)fm9A{0) z>y9hmZ@7Kh$=+Y=nI7#ANkY4v^5~@>R~B8-5Gp>kvO`lSHK=#_zSZ%9rAAngD^w&* z8;-IBN|nK&5AIV?H+mCxPh)RUvUf>UFuGE9hsW60?kwS_I@|)M22XU)F|3MC0 z229OWiejZC_+iNPP(GD*H>Hk zadDB-spx^tHbqyIfe|eUJkx1Zj8PpA9qJ659J}Qq+yFzd$5Q^)K*g-5*iMZKFMI=V zxNtOx?g`y9%0gV+hpF(xZKX<`^aS+aITji07N|HsP!_~MsWv(g!44;6LftW?LgTcB z#^c<09_Ho%Y&v(#)t9n~$MQpH2M<>l)@Wd_AqhOuUX1rOAB#CN`{e>2S#6SOBHaN4 z2PWx2F+PS59PB@m3!8{yMSOo8j{$G85Bkvuhkq)ms`oR7%#(1m{Uz%xDld^mv5C>Eh0lh3-XZJ({ zrX>}>FPvp~Zs(_{0IZI18H|k)6G~3_>#HqmcXYY8KiOhy`mYHkjRZcVuyDbG*q>f{ zc{Qx7quo8-t1tmgF}GwfTx{cc;S3cO<&s|PsE2GKFtxO=TM{_!FPWIY+d)8zfK-WM zBdc&qB@bwcXi}yyx=p3f?lO6I0GzH=4o2k@&I{kbg$9+B$rY+ksaP#!EYsbL6& z69r-Z%}y`8Y0w1oLqDXdUd#tScR2hGLzlBfKG|s3-#O!S-z|IRg!kb~>4`|)8}^Jh zb=NF5Tw1%k`&aGXMCTCRk7jX&(>7Jz+SxMTLK!ZQ4t5)YLr!d*N}^bpQ0uB@7uRUM zJLX%yXU#eolS|ysnTrjlS5#`hRqPGy^uP@Ze9u2)E`b(=yZ(m^Kv_`nQo|!NC?w&r zDyPrshL6~^rB}cpQ0E;ab4jB;`Cx`P1UN#&K?3}q6P9$v1;T~l-xGS1c(cU( zL-z%qPsc8O;njGyb&74`NvXL5*Ca5&#-3P!K{k}m_k%u& z70pC1&UF9Wi9TrWayH8+8EyK_)6W>}gWhBx)VGa0t>p3=uclBDw9`W>@yC}mW)8?) zziFZ9&g-C%j%OUkt+Hu4v%6OH!S3C5*G+40_N?FVbK%UFgECGlTXNldopuvCd%O9%L<$lTC3vGct|Vu#lk?yToa zWFUhRFAgbM_>zeg;?l#}0gvFNx>JzKJYF0#lFZLM{3>#hj|AY6B&DS#k2H+0zY0tZ z7O*1*a{K{onzOTm%J2ojgem562fgsN=v0N`4#u+%SQCdmUMvMbI{^kHDd|f{R^0Hj z#MWE3xPA4Jy%=`>s43<&T~T8ztkawjc&xLEN-CPLdR#%jG$wQFf>9gyVew0d`CY>6 z4f$Z)<$-+eQiLV;`cI<)c1Z>figTX6CUNP-uk#c}E10hn^T%4Y6~<9fj($?=8G_idS-L%e?3wH$+;Q#PNi=Cisb~G}P|bD0GnO%L^iblS}sP z-(%^qbUE74rv0dr$1;!}B6~{c^sw+zNyk;6Jtm;oZaXFJh(LCM0nx8oON^J*x9GZq z((rDtNrr*L)sqneaF>^0FVxAU{no-*ueUwmL7xb7ej?R3df5{g>5Z@rDWu73>TCqD!m1 zn0tON@H_KZ&c(xfeT4(7zgQBwtR`A?ZpDYDtLk6#Z0nmB?Fq|HBh6l4s_dN z=o`c!i3R!#p53uAJMD9MQl={#Iec64`^K{RI zaIL3K@rW%L@L0``4oLfLI-R1U_WLFMibm6dgeNftTQv+|2J}kJ zV}EnfhcgXys~F}Veru1j&*KdCV1Jhj?G?siVI$o#M%?PThL_8?%?^5!v?)P*ZC+cz zgZwySn%qqcF>lZx{XB7I=>v*+Mf(%3_zWnbX%hoHgfp^o;=%V0p9cvy3=FJ(w5i+G z34x*8X%DoQuCBgcbxHLcrz<)>)dwvH_rd>$w&_40l%o$~ilfCg1CP@aG6x;Oe#5e{ z&lu0GoCrg_2^jt**kcFJl00HsSPCJX)7p`259M`e6ny=WV6Szry#!~s8^HrO+sVz? znC+-BXT0}z$Gw;Cv%UBrO4PsIe$S5<)U6&gzDX86y1&bpE&bEBZO?r?U>mprZmKQ; zTf_FMVgO`5cHkjy`Rp74d)zWqaNK~T{(j<8Ju#&W{Wd1@cvgAJA9iwFx`GBWPJ zN(OwcA^pXuO$WjyC8j@DjvagB`RAYe$>^{Yp`wVsELBJR43;N_{jaJsL)u}rjp3pR>FEq~Y3PF1u>4sR3^LR7M6EQ^lBQRyR^o2rA z{qU%Qywly@P%&@;e~6J8g)1tOOcu<||M+9~?=LRa_&~7km{c|mOtTuD6D4fMz z4dyP1?{QjjR=QKERzRI5;}i@2%>=oPbjhF%+rpU?m{=kljKuxkFyxE~U0yXK$&PIj z!r+x@vD+f?hR+4xgyvAtZ*vD*o!-!RFSZU~VF#oMp<}hdywnO= zYC68Vm1rlYwc?=7pbyKzJK&auILd*6dAJwll0k@jiLh~5ppDlVjC^hm2mCfqsMX~Q z)q9h{o`ybHlGz87wwz}#`BAPuScUfRkjDXeucW)sqqHg2 z@|I92(E#t*+-ykWdIv;) zoS=w2!0RC5U$XMb*qxg<+aOWmqaf|WyVwILa0~Pkf27yDGwi@%vtmHOGm1o5=Ku_C zA6$SFq!v791ZmRAf&cEi@9cv_L>z&OgzIk9jrRfAhw=s~v~2n1A>i=#dy$JJlB6v_ zH})BE%TgCE8gH=&5_c{ipnC3k5v*r8745+WL+@pmU6m6Tq{n{qz&&tR6$=6n>`<4G zp<%$n%2e3*!nY-?mFN)~P| z@iBjw@Es(~D61H0g}94f=^=^&G&H41bmHP^09HDL5P?Y>NTLp`!!={&7am~}ZMfK8 z(q)h~BK+jZ-w)v&qh6>UxsKigIH66r52?7}7(|&Yg0dj&kc4vkJ3CzPSmVKp6Har= z*&h##*i?Va?t}ai^F6yz2inIEP=a*k7~=;3_404-kcJnXJh0ymws%-2$Knj?s zQ}m8t`=xsaUV7^z^J71nTebX++*OSnd+ra;c?(c)J^uKU3;Qg6KZHcK7{_>2(guKj z{%}AVrlT5R*F3eH+-8sr92;zR>T`#da4n6}pF*K<8jOZF#*~kFs;H>wFK3*7Dm&Dd z3QlJr0)r+HO7Og*0ujkHuy`7yTU&5k9_z~Uu89$hvEZWa-19EY`5LZXvnH`&{YJl1 z$qkHBT1F3+hd~uVQ+PxyI2%DmFM!VqUCb4PbCiWN7o`Z{v^c)v-7E4+XCzekJ z#Sb;Q!6+3}1^f{gq(l~({v zD~rDms%PZVB$6~-2Jss%UmAQau*6}sMZ}xsWz!)&EmwVmai}+gnGGhSJ!IiNEUwwG zEM~a2rQivcj`Lt0S>+LKq%fE_8}JazI-K`9WZmhw93mdfnzP)ja&p3qqF%N$o%ZQj zMtaVubJT^r*Kxnx5p3Jk=ljRioPQS=G`v%;o&NLrb*tYTsm9T!|NeK|v<{cEs-&c( zy0^El!tHjOj0Qsy4uq4!*#Sjy*Ys&qZ7#Q~9iP9>3zsh&jmA^*UdIDd>x+){R2q-Q z*FGQe6v$KH-<<-ZW^5uMc9wLK!!e&)A=gApG?Shjr~k&5V=906xd`*Ga);SU z!+?L^S=dOsZ%WDHKaVrcrU;!6c?#qy@NZ6mLuPEG#|NFiS={RQ>%GC4yMe2FDuux_ zMmz0EwW8?3h4okeo|7)$qM}%W!YcL3MW5pR9C%z^w{&LsrXvLr+v?>&|op zTW$)(9LFTM>j;V#nssOu#Vsni{tdly%&R6%!w3GTt#^Ly>g+{kv6#cU|D}0tky@df z?F@FF7>RjL^+yM0q0W!Xw9{`osbSrp53A68raT4m6!i%)}<%%)7=?0s>xk4i^s>4Bj(^2+ZchEdLlJHHW;k8y#vZvB8_b$0i{lvFxE~mOZ zAMzB)Q{X?80!M_giL`5K-CQ1t`|5zpujnakudRaqn&7>hjmSR4)zV6LQw zV_&tr_?>dy%ts&@{&8;AQl4U%5B~-f`1#L&-i~I}!ba)n_3PJXtl{2p!ws`=Fv4IQ zwB^U%dh4w_(wlwLO*hSk_0T6U9csVjmRsu6)5PcNufKjOcD}5_?-OuU0hZmATJ$$y zPkHagjT?tGCjyQK%|K8F?c>_<;e7>V+;Q7&x6zO~XAtw>eDlr8L6U-6vSf*J>eQ(( zpp3vGJt z;CdJF&!DWo;W;A=fpZ27f27lqMu|r(G>%_GOZs2E({cAB;izvR7}S}*h;CYi}}Y27c%W<$SKiU_zPK+larEu|u z{e=k)?BlS3THKPyRtfzKme;Z{_7?<{O05ghTE9}R-HUa*zr#t#dpdQ+?&GR|JSuxO z5vTn9{}u%>pqtRqMaFhd7WN`zdkgUk0Y}ERIUNRZjr`4Wcux-)WLIK9a***W`v|0t z2eBIl`)1>DoF+3JQpHN-zZlo;U~WM$w|mp`XFsP)3Rho!bs5eJoQLx7LjLh!6dM44 zes-Q*zago~AgMiuw6mBF+^<62*=^@`LozxtwQj(yg)#eUu>b4_-WvF$48;cCF$ ziA2)-agcc{B*V{eQjZrtI`wcs+<^G`fH^N`0jbDzoQH#B+E>EZ(kq=`ca;;r-%efW zN%`kI1%{*moXNh)BdZV=aKJzN?6YwZ7z1EFpE0;@!Sn05j!%c-vj~Gh^ro1P_iL}c zwi;=I1cbDUAq_p6o{r~_c!Bx7kAc1w&zm8^JP!%RoCTNj=bd-nX+^?|$TI*2@h+ZE z%n6ty5=`v@;Pyi#p=pWB!PI`81B{8M0gltavw{EiG#G9%;%{CX)8dDH#FVuk0KW$V z!qzP5>nQ(}p)!C`U(7VX{T^_Xt}X(d7z`HXoAd`;2O>m3)u2V2G8=#autd-J|3X3jA_8} zVMvV+^BM5Vn8xSq0IBdNh~pmBr*bg3Z15xYJI~~f7%B4weFYR~Vwo5?jl8GALf#R_ zDJcVI20WIYQ&S<}xiR(Fl)4Yzkng0_kB0^$hj_ri6=6m#fr&+dfgY23Hj8mX-61t` z-S0{;4e*Qjge-MgP{onV>zxyfC=kP zm;wom4GchFY=C(i=@;N4V-pS?O~G?8H6boL2#f#{6{kVN1~9gd!6XSYYUY9Us8ZzN z+Rx>vPcM?RVdOw+SJ2 zqC`ejIe&1C5Qn}tia6t*(;gJGU%>)U$0KP4@p%jKFzrui@xmk8)POYlDItDeDh#J7 z&0dRBe5so9ne!C*3MqgA^d<%qYe-*n6C^VX7=f{IAd~rE@Ca*g>1%CJ4!oI-9`flq z&}=rFJ3B4=cS}o)3))IDr(vg)!wk4*cJJQ3A-mjRe#eJN8%%Rf9almJ6T^6_m>t>ax=M<##-1gs!>0nsD zg<@kP(iUHH%{621xZ{rO9Y6-cj)vZ1nMdNDXKY7;iup3W5(;pw3&s4~QO;0i}UQquWlFseIp*|ed&O5 zj#$SMOuv`oo~^*(2c&p3^ak9pAzLaN4mi))hNDhC?O%ZcO+ca^1FsR1fnaWc-*2ZQ zhO~F^dkF?Nr8!+HttoZSzR^TsE(Yp1aQ|y|V)}2?C#;iU;O|e5&wdsM9Hd3%HvU75QreHD{8{$a2V$fnX?r-GE z_f^EnzKTNgW#%bxq$q%a-o&ynKpJt&SYKm217HM32bcvZxS`h92>u%XfU#Y|`v^gV z5%P=xE1`5o2@(?5a=^ZVs|?=PD2t@(FuFt5#Ih2a$iQsoc0Qx5 z>AZj00LiZrWi*Ub4(gi#ya_uP(5BZ@KQ0`M{2CtqQyE+PV;{iSylV0(CoVesYanyJ ziX%aRv^6s_FoDUTTw$$EEI*CO(TI0G!mQql$KY3a`xtlUm? zHp&hI2j)4HfDJUUE07llh9{PRNpP3Lhyjd_+mN;b5LHVb0Dh}R%#;HFlG21!v?%T7 zfEs-iJ_r}5px0CC%XJ}reF{c|6@G#a58xq!_M8uz{vZYOmEZEy(yyGv`3k-a1-NF0 z0nv(qF&^cZaM>_r+m&7>e(%Io$$_})RQ!Id)tS>_#AmMIfni(^3F%H;k0alFFuRAq zymrB=KLN)MO*3#(qM#2L3oSIIijW%GbSP{zM zKGg(h^ypCez`(YG0j>qyS;(^r_K8lyrqdf~PlMjy1-&1|_34fsJAB6;d#paih^bXR z4{e=0R2_#BFI`dc&_JHM9SX_vu>ULyG@)X0HwMl_6T;JhKm7eJuG3OcO{sg%8@S;X zaJT}DCT?rE1dDaN1W!X^28`%9p4S5QZZYmq?-=nnqg>jioQ3-4psW#XPB^!OhF}>~ zooeJe8y9iqBAhVaBo2t91@km;lN)eJYHMqAp|%?wWKFJwLx}_DIUn^EAkXW=ZHNUo zZwKe%9R4J5Snit|+)|OEH=K(KT>e7PgqLLD!i9%|iUj3nzxRy%=?jVfsdLi|g5-bv z%TwS@5krV78FSHG@nA|#V*F5d47OV_@Mi*+bIoSl{kRACjO)Ld1`*;mJRf#|$kKz% z_u>L?kY=p14_7EP1Q6fI99|+E7{Vqnx0}Q~puu$DOVR8V+~M<2@FxkkXo)_=alh0m zh@i&|ckGB*)<}2MEzB=b=OZJ*qTYuIgSM{7h9zSLqn`qpdyuvhcdAcm%xA~-A)dE@ z=7Pm=cHaE&JO%O;$WtIsfjkBB6v$H`Pl10&3cR=Cse+R}xaUV~+bJiVe&X{dEWhRd E1KAAi<^TWy literal 0 HcmV?d00001 diff --git a/src/main/webapp/img/d4science_workspace_logo_180.png b/src/main/webapp/img/d4science_workspace_logo_180.png new file mode 100644 index 0000000000000000000000000000000000000000..0def337329029834fcbaea03e29b780b96c3eb38 GIT binary patch literal 35508 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 literal 0 HcmV?d00001 diff --git a/src/main/webapp/img/dark-noise.png b/src/main/webapp/img/dark-noise.png new file mode 100644 index 0000000000000000000000000000000000000000..be1965dfc8a4e4d362f8ac338f63a69dce3ff994 GIT binary patch literal 5091 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 N002ovPDHLkV1iJcx(EOO literal 0 HcmV?d00001 diff --git a/src/main/webapp/img/gCube_70.png b/src/main/webapp/img/gCube_70.png new file mode 100644 index 0000000000000000000000000000000000000000..018d52c09c22423b950d764a62aa182fdb8b77cd GIT binary patch literal 8275 zcmeI1eUOz^8NlC#VA%yS(ID1xWg(ftCaol`rch^L-2w3nzlLzP2H7Mar*vS5%&-<^ z8X6W|5t;-nBnCB0iKPBeN^-PfrnHzHlFT)*h7?5PWB2y^o%^2a%jI6N&1Ralhxy&- zoaa36`FPHA&iewlUoyF2aCJ>}k|cv0FRZ@|Jpn#2pg+IET55iT>i_wP4fRRRKdXLm z-!d#!H(YqlSCZt^$E9M{~f-aOLQE2kMigc4uS#`BSd0s(7Y$ z%uYPs9%*g6`?wvo-cjBs`+T+>JH2&j`Ddd~)OF46$*8F-V>KDsv^*Kn)Ly6`uTa-? zS5k32r{lG|i1~9`3U1WjMWqt@rp7MxA$$&7PZ!;X;sEQ2?FX}cXv9w+`*Dsr+7CG4 z)E4`;9wkTN$e&kVAI8y``X|_;k2bT*=S!{q2=+tzyNDi3HYk+)(a~ve0W_p#2mcFf zru}E==iv~X2Cd*Co`u`Mg=J+FmD%ua*ax$~K&d|hE+UHKguYn#Cd%7cTvv&JjG=8J zj0A&|9n*k0$F*>{$AKvd$_aEf6>f%Mkd?EjTnsMmtKhNM=PFRPf`KWP;TW1>5bOs7 z;(RZHaZpa2!}SDcy}{8b&64XVwt<;gP7czr9(o>_nEC{0FdZ#`8zIW;6kbXzL(v`^ z{bs)XfZ0n)e|2^;+gltIrF^Ima%)*a? z>zWBIpv=vyaNM4t?CZJh(9c^7%!uaYNkuMKL5CsD z?9ZdbA}3KClJ;-f&c(hv4I1aAn*-fP-%i?okox^c%1JYia(%p?244coYk3v2*0M+0 z%eywUAERR5_J7n-8p)vMKey@&c9P@4Dd+~M9@sCL$5u>8BjvywV^9oQR$7}z%xd;`Wn(v?dV(`{}3stRwMKWHx{Z&y$)ww zcjv{(dl4V?v6pZ9ulzb*VN*+t@Ih=RgPW=ENH8enJaF(95*1k?4j^=mQcm!lE=8)yPE$Y(zbOQCR#D8DfwvZk8)W#A>Htb}?p=@PUVv>z02zTA+i za7I0wN+mRK>DGC_#LL%)Y}q<9b&>95l#?j95y3a(|8Y!J+L6EJRpIvlr7hqlu7~@X z=L&Qy_~ubQ0Ws*G43;G6M9;%_4SECk>{@sl{H`fTHii0Q9hJ7|)Zy_;1#r z3IdR05kIE98-{_|wiMe8+Wv-iQb8zt>0J)@%$?KHMcr)M24}$;a1*wf=>2KGXHuR4 zj;DkT@W>-(K%s99shEY1V|FWXp>9MhyI!+fIVMZ#U*B%moehi^m5WylQua)qNIeet z5@kD3_QIE7ofTvfY-N$l(e9{z=Ypwx3Ut6@;Evx8?zl1y&VfgH)(n~qF(}Sy87R){ zS}>T|zbkdKs3F)cg}CsaQ+7=TaWh;4ZeSa}QErjAPU1%(lB>I`oCpQ&0ujN2v*aH$!pq zQ{g;#GwG!9PB1Wv^O*>4b`8viQeyi?I1Q68M+~r@vV(4bF z;Z8swrtZMA;8}PTibb3KY`Cp$Wf+s^UZZ{kd=on0pKuTy$K&}VT!Eh(5ycFQ{p(xI z9&EpbDbVSWNclZ=1NujJ8H%5?t~e*h$RDMH{R)X=);tb&@^{z{?xs8UYq*PnECfrB^^-vsOMH~W%BZ7XQV`D!jZZ+fU+tlzF+98%{K{>I z8hBsbwe3E1lwdE^op`Ze>jMV0tdx4L*g5)S$1C~A0zx>oJ>U* z)B#4=8$F~y+EmrHmR*VGm+BkhLd>MBw6-myT8Vu|*8D$RuBhYRL(M49B7qq|#Z`DA zmJ`!-3H}R>tk3mEAu#PMZl*!;^|%l&hg$G{c^;Jh;4AWEE64#DN>JiO7>vE?Cmbb$ z;_Z7Cd>_30%$g+-ML&Hu!RXX@I)U-H^-6KEiu&A8%70RCVbPswy`TtSylb?*SZL^l zg%}uLb@A8?r#zn^3_|aKYWNU*4(dR;m%#aI@3j&#fJJ(I)`H&$%2-$pzXU(}z5{21 zZ>t9(+_(gfV(*lSx@qmnp~|l0h40Sx0zQFdx@bRwMnM($HTVKN1#1Z67PP*-_KoEF lg7oCSFypiT*YB_h?0WG21+}l9;Ympv$4{<*;DY9b{{mg{&bR;o literal 0 HcmV?d00001 diff --git a/src/main/webapp/img/glass_cursor.cur b/src/main/webapp/img/glass_cursor.cur new file mode 100644 index 0000000000000000000000000000000000000000..a22038eebc4f2952cc77f19010b289943c77a5be GIT binary patch literal 2462 zcmcJRPe@cz7{$M77HLVN7B%9+Tx21E{aHneX;a|Fphe)KWs4A6wh_!-;>KMlQbWJ>P$59vqAT!aPq3G61eY9~qA4}!U3dwU;I|J9q^;!<+CNE2v zw`tB5AP1w6Fjq?2HtkTfl;yX(Y;GrG6Qzu0UBK7MC~g0o`MSt;dg E7b&TDEC2ui literal 0 HcmV?d00001 diff --git a/src/main/webapp/img/glass_cursor.png b/src/main/webapp/img/glass_cursor.png new file mode 100644 index 0000000000000000000000000000000000000000..32f491c90bf6934968491b673231834582be5d61 GIT binary patch literal 532 zcmV+v0_**WP)1uvCm#_m#LP!XJ~l>MQ&Vu^Vn9Ygv5kl;kwC#DAwmRKVz`hJH%To7 zCB+AVfgB&hlQIcH!P?wz@Fn*%>a=5fAz&&)knkBU4Vp%5uJ$3Fh5 z7>38YS)6jxGOrallP6Ihu#}|CWzX+f6 zVg^TOcM|ZJqg}%Xhs&F6-Y;h|7A@dI4_-z)<*@M#zs%!Bq<|dBC}v}rJUFJYVRsf1 zNX0QSaqS||gf=wV1zzAQ%3Mq?qX6?}nJfdc?jv~RGVlbO$h8Z|5&Xncmw|Fjnn%k( zBF^v}CoTeAs6dBZK$#;rz_5$J7T%jxunm-8Rp~GMG=|BW(ThrDbLEF_6$5yUTKsV^ zxlAfo{~l^^6)hlte>UqW8`@!n$$jR%Z&8g>ys?T{ZP%R`!~%X`SLy9KOX;7qY;F&5 zW6t0m#?3O@Ub9qk(LF?2yaO_lP^I*L9hdiY W{a{*DiMiSU0000