From: bsinou Date: Mon, 30 Jan 2017 22:44:06 +0000 (+0100) Subject: Add a core bundle to keep separation between Workbench and web clean X-Git-Tag: argeo-suite-0.1.1~17 X-Git-Url: https://git.argeo.org/?p=gpl%2Fargeo-suite.git;a=commitdiff_plain;h=f2bf1e12e3aad9c2507e86e1d33fef2fd3e67489 Add a core bundle to keep separation between Workbench and web clean --- diff --git a/org.argeo.suite.core/.classpath b/org.argeo.suite.core/.classpath new file mode 100644 index 0000000..191b71a --- /dev/null +++ b/org.argeo.suite.core/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/org.argeo.suite.core/.gitignore b/org.argeo.suite.core/.gitignore new file mode 100644 index 0000000..016bb39 --- /dev/null +++ b/org.argeo.suite.core/.gitignore @@ -0,0 +1,3 @@ +/target +/*.target +/bin/ diff --git a/org.argeo.suite.core/.project b/org.argeo.suite.core/.project new file mode 100644 index 0000000..e3b8ec5 --- /dev/null +++ b/org.argeo.suite.core/.project @@ -0,0 +1,25 @@ + + + org.argeo.suite.core + + + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.pde.ManifestBuilder + + + + org.eclipse.pde.SchemaBuilder + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + diff --git a/org.argeo.suite.core/META-INF/.gitignore b/org.argeo.suite.core/META-INF/.gitignore new file mode 100644 index 0000000..4854a41 --- /dev/null +++ b/org.argeo.suite.core/META-INF/.gitignore @@ -0,0 +1 @@ +/MANIFEST.MF diff --git a/org.argeo.suite.core/META-INF/spring/application.xml b/org.argeo.suite.core/META-INF/spring/application.xml new file mode 100644 index 0000000..460fc85 --- /dev/null +++ b/org.argeo.suite.core/META-INF/spring/application.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/org.argeo.suite.core/META-INF/spring/osgi.xml b/org.argeo.suite.core/META-INF/spring/osgi.xml new file mode 100644 index 0000000..3301729 --- /dev/null +++ b/org.argeo.suite.core/META-INF/spring/osgi.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/org.argeo.suite.core/apps.properties b/org.argeo.suite.core/apps.properties new file mode 100644 index 0000000..e0227a3 --- /dev/null +++ b/org.argeo.suite.core/apps.properties @@ -0,0 +1 @@ +argeo.security.systemKey=argeo \ No newline at end of file diff --git a/org.argeo.suite.core/bnd.bnd b/org.argeo.suite.core/bnd.bnd new file mode 100644 index 0000000..68b918c --- /dev/null +++ b/org.argeo.suite.core/bnd.bnd @@ -0,0 +1,8 @@ +Import-Package:\ +javax.jcr.nodetype,\ +org.argeo.node,\ +javax.jcr.security,\ +* + + + diff --git a/org.argeo.suite.core/build.properties b/org.argeo.suite.core/build.properties new file mode 100644 index 0000000..3166058 --- /dev/null +++ b/org.argeo.suite.core/build.properties @@ -0,0 +1,3 @@ +source.. = src/ +output.. = bin/ + diff --git a/org.argeo.suite.core/pom.xml b/org.argeo.suite.core/pom.xml new file mode 100644 index 0000000..a8eb095 --- /dev/null +++ b/org.argeo.suite.core/pom.xml @@ -0,0 +1,22 @@ + + + 4.0.0 + + org.argeo.suite + argeo-suite + 0.1.1-SNAPSHOT + .. + + org.argeo.suite.core + Argeo Suite Core + jar + + + + org.argeo.connect + org.argeo.connect.people.core + ${version.argeo-connect} + + + diff --git a/org.argeo.suite.core/src/org/argeo/suite/SuiteException.java b/org.argeo.suite.core/src/org/argeo/suite/SuiteException.java new file mode 100644 index 0000000..6351804 --- /dev/null +++ b/org.argeo.suite.core/src/org/argeo/suite/SuiteException.java @@ -0,0 +1,14 @@ +package org.argeo.suite; + +/** Argeo Suite specific exception. Wraps a usual RuntimeException */ +public class SuiteException extends RuntimeException { + private static final long serialVersionUID = 9048360857209165816L; + + public SuiteException(String message) { + super(message); + } + + public SuiteException(String message, Throwable e) { + super(message, e); + } +} diff --git a/org.argeo.suite.core/src/org/argeo/suite/people/PeopleSuiteServiceImpl.java b/org.argeo.suite.core/src/org/argeo/suite/people/PeopleSuiteServiceImpl.java new file mode 100644 index 0000000..27efb4d --- /dev/null +++ b/org.argeo.suite.core/src/org/argeo/suite/people/PeopleSuiteServiceImpl.java @@ -0,0 +1,143 @@ +package org.argeo.suite.people; + +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; +import javax.jcr.security.Privilege; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.argeo.connect.people.PeopleConstants; +import org.argeo.connect.people.PeopleNames; +import org.argeo.connect.people.PeopleService; +import org.argeo.connect.people.PeopleTypes; +import org.argeo.connect.people.ResourceService; +import org.argeo.connect.people.core.PeopleServiceImpl; +import org.argeo.jcr.JcrUtils; +import org.argeo.node.NodeConstants; +import org.argeo.suite.SuiteException; + +/** Default implementation of an Argeo Suite specific People Backend */ +public class PeopleSuiteServiceImpl extends PeopleServiceImpl implements PeopleService, PeopleConstants { + private final static Log log = LogFactory.getLog(PeopleSuiteServiceImpl.class); + + /* DEPENDENCY INJECTION */ + private Repository repository; + private String workspaceName; + // private UserAdminService userAdminService; + + public void init() { + super.init(); + Session adminSession = null; + try { + adminSession = repository.login(workspaceName); + initialiseModel(adminSession); + } catch (Exception e) { + throw new SuiteException("Cannot initialise model", e); + } finally { + JcrUtils.logoutQuietly(adminSession); + } + } + + // HELPERS + + // TODO Hard-coded creation of default public and shared file directories + // To be cleaned once first init and configuration mechanisms have been + // implemented + private final static String publicPath = "/public"; + private final static String sharedFilePath = "/sharedFiles"; + + @Override + protected void initialiseModel(Session adminSession) throws RepositoryException { + super.initialiseModel(adminSession); + + JcrUtils.mkdirs(adminSession, publicPath, NodeType.NT_UNSTRUCTURED); + JcrUtils.mkdirs(adminSession, sharedFilePath, NodeType.NT_FOLDER); + initModelResources(adminSession); + if (adminSession.hasPendingChanges()) { + adminSession.save(); + log.info("Repository has been initialized " + "with People's model"); + configureACL(adminSession); + } + } + + // First draft of configuration of the people specific rights + private void configureACL(Session session) throws RepositoryException { + String memberGroupDn = "cn=" + PeopleConstants.ROLE_MEMBER + ",ou=roles,ou=node"; + JcrUtils.addPrivilege(session, getBasePath(null), memberGroupDn, Privilege.JCR_ALL); + JcrUtils.addPrivilege(session, "/", NodeConstants.ROLE_ADMIN, Privilege.JCR_ALL); + JcrUtils.addPrivilege(session, publicPath, NodeConstants.ROLE_USER, Privilege.JCR_READ); + JcrUtils.addPrivilege(session, publicPath, "anonymous", Privilege.JCR_READ); + JcrUtils.addPrivilege(session, publicPath, NodeConstants.ROLE_ANONYMOUS, Privilege.JCR_READ); + JcrUtils.addPrivilege(session, sharedFilePath, NodeConstants.ROLE_USER, Privilege.JCR_ALL); + session.save(); + log.info("Access control configured"); + } + + /** + * Initialises People resource model and optionally imports legacy resources + */ + protected void initModelResources(Session adminSession) throws RepositoryException { + // initialisation + ResourceService resourceService = getResourceService(); + resourceService.initialiseResources(adminSession); + + // Resource resource = initResources.get("Countries"); + // if (resourceService.getTagLikeResourceParent(adminSession, + // PeopleConstants.RESOURCE_COUNTRY) == null + // && resource != null) { + // resourceService.createTagLikeResourceParent(adminSession, + // PeopleConstants.RESOURCE_COUNTRY, + // PeopleTypes.PEOPLE_TAG_ENCODED_INSTANCE, PeopleNames.PEOPLE_CODE, + // getBasePath(null), + // JcrUiUtils.getLocalJcrItemName(NodeType.NT_UNSTRUCTURED), new + // ArrayList()); + // String EN_SHORT_NAME = "English short name (upper-lower case)"; + // String ISO_CODE = "Alpha-2 code"; + // new EncodedTagCsvFileParser(resourceService, adminSession, + // PeopleConstants.RESOURCE_COUNTRY, ISO_CODE, + // EN_SHORT_NAME).parse(resource.getInputStream(), "UTF-8"); + // } + // + // resource = initResources.get("Languages"); + // if (resourceService.getTagLikeResourceParent(adminSession, + // PeopleConstants.RESOURCE_LANG) == null + // && resource != null) { + // resourceService.createTagLikeResourceParent(adminSession, + // PeopleConstants.RESOURCE_LANG, + // PeopleTypes.PEOPLE_TAG_ENCODED_INSTANCE, PeopleNames.PEOPLE_CODE, + // getBasePath(null), + // JcrUiUtils.getLocalJcrItemName(NodeType.NT_UNSTRUCTURED), new + // ArrayList()); + // String EN_SHORT_NAME = "Language name"; + // String ISO_CODE = "639-1"; + // new EncodedTagCsvFileParser(resourceService, adminSession, + // PeopleConstants.RESOURCE_LANG, ISO_CODE, + // EN_SHORT_NAME).parse(resource.getInputStream(), "UTF-8"); + // } + + // Create tag & mailing list parents + if (resourceService.getTagLikeResourceParent(adminSession, PeopleConstants.RESOURCE_TAG) == null) + resourceService.createTagLikeResourceParent(adminSession, PeopleConstants.RESOURCE_TAG, + PeopleTypes.PEOPLE_TAG_INSTANCE, null, getBasePath(null), PeopleTypes.PEOPLE_ENTITY, + PeopleNames.PEOPLE_TAGS); + if (resourceService.getTagLikeResourceParent(adminSession, PeopleTypes.PEOPLE_MAILING_LIST) == null) + resourceService.createTagLikeResourceParent(adminSession, null, PeopleTypes.PEOPLE_MAILING_LIST, null, + getBasePath(null), PeopleTypes.PEOPLE_ENTITY, PeopleNames.PEOPLE_MAILING_LISTS); + + if (adminSession.hasPendingChanges()) { + adminSession.save(); + log.info("Resources have been added to People's model"); + } + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setWorkspaceName(String workspaceName) { + this.workspaceName = workspaceName; + } +} diff --git a/org.argeo.suite.web/META-INF/spring/application.xml b/org.argeo.suite.web/META-INF/spring/application.xml index 59fd51c..aaca5d8 100644 --- a/org.argeo.suite.web/META-INF/spring/application.xml +++ b/org.argeo.suite.web/META-INF/spring/application.xml @@ -6,20 +6,6 @@ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-2.5.xsd"> - - - - - - - - - - - - - - + - - diff --git a/org.argeo.suite.web/pom.xml b/org.argeo.suite.web/pom.xml index 998fb83..a252f56 100644 --- a/org.argeo.suite.web/pom.xml +++ b/org.argeo.suite.web/pom.xml @@ -11,8 +11,12 @@ org.argeo.suite.web Argeo Suite Web UI jar - + + org.argeo.suite + org.argeo.suite.core + 0.1.1-SNAPSHOT + org.argeo.connect org.argeo.connect.people.web diff --git a/org.argeo.suite.web/src/org/argeo/suite/SuiteException.java b/org.argeo.suite.web/src/org/argeo/suite/SuiteException.java deleted file mode 100644 index 6351804..0000000 --- a/org.argeo.suite.web/src/org/argeo/suite/SuiteException.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.argeo.suite; - -/** Argeo Suite specific exception. Wraps a usual RuntimeException */ -public class SuiteException extends RuntimeException { - private static final long serialVersionUID = 9048360857209165816L; - - public SuiteException(String message) { - super(message); - } - - public SuiteException(String message, Throwable e) { - super(message, e); - } -} diff --git a/org.argeo.suite.web/src/org/argeo/suite/fs/MyFilesBrowserPage.java b/org.argeo.suite.web/src/org/argeo/suite/fs/MyFilesBrowserPage.java deleted file mode 100644 index e34f964..0000000 --- a/org.argeo.suite.web/src/org/argeo/suite/fs/MyFilesBrowserPage.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.argeo.suite.fs; - -import java.nio.file.spi.FileSystemProvider; - -import javax.jcr.Node; -import javax.jcr.RepositoryException; - -import org.argeo.cms.auth.CurrentUser; -import org.argeo.cms.ui.CmsUiProvider; -import org.argeo.cms.ui.fs.CmsFsBrowser; -import org.argeo.eclipse.ui.EclipseUiUtils; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; - -/** Default file browser page for the CMS */ -public class MyFilesBrowserPage implements CmsUiProvider { - - private FileSystemProvider nodeFileSystemProvider; - - public MyFilesBrowserPage(FileSystemProvider nodeFileSystemProvider) { - this.nodeFileSystemProvider = nodeFileSystemProvider; - } - - @Override - public Control createUi(Composite parent, Node context) throws RepositoryException { - parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); - - if (CurrentUser.isAnonymous()) - // TODO implement public file display - return null; - - CmsFsBrowser browser = new CmsFsBrowser(parent, SWT.NO_FOCUS, context, nodeFileSystemProvider); - browser.setLayoutData(EclipseUiUtils.fillAll()); - - // TODO set input on the default home folder parent for one user's - // files - return browser; - } -} diff --git a/org.argeo.suite.web/src/org/argeo/suite/people/PeopleSuiteServiceImpl.java b/org.argeo.suite.web/src/org/argeo/suite/people/PeopleSuiteServiceImpl.java deleted file mode 100644 index 27efb4d..0000000 --- a/org.argeo.suite.web/src/org/argeo/suite/people/PeopleSuiteServiceImpl.java +++ /dev/null @@ -1,143 +0,0 @@ -package org.argeo.suite.people; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.Session; -import javax.jcr.nodetype.NodeType; -import javax.jcr.security.Privilege; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.argeo.connect.people.PeopleConstants; -import org.argeo.connect.people.PeopleNames; -import org.argeo.connect.people.PeopleService; -import org.argeo.connect.people.PeopleTypes; -import org.argeo.connect.people.ResourceService; -import org.argeo.connect.people.core.PeopleServiceImpl; -import org.argeo.jcr.JcrUtils; -import org.argeo.node.NodeConstants; -import org.argeo.suite.SuiteException; - -/** Default implementation of an Argeo Suite specific People Backend */ -public class PeopleSuiteServiceImpl extends PeopleServiceImpl implements PeopleService, PeopleConstants { - private final static Log log = LogFactory.getLog(PeopleSuiteServiceImpl.class); - - /* DEPENDENCY INJECTION */ - private Repository repository; - private String workspaceName; - // private UserAdminService userAdminService; - - public void init() { - super.init(); - Session adminSession = null; - try { - adminSession = repository.login(workspaceName); - initialiseModel(adminSession); - } catch (Exception e) { - throw new SuiteException("Cannot initialise model", e); - } finally { - JcrUtils.logoutQuietly(adminSession); - } - } - - // HELPERS - - // TODO Hard-coded creation of default public and shared file directories - // To be cleaned once first init and configuration mechanisms have been - // implemented - private final static String publicPath = "/public"; - private final static String sharedFilePath = "/sharedFiles"; - - @Override - protected void initialiseModel(Session adminSession) throws RepositoryException { - super.initialiseModel(adminSession); - - JcrUtils.mkdirs(adminSession, publicPath, NodeType.NT_UNSTRUCTURED); - JcrUtils.mkdirs(adminSession, sharedFilePath, NodeType.NT_FOLDER); - initModelResources(adminSession); - if (adminSession.hasPendingChanges()) { - adminSession.save(); - log.info("Repository has been initialized " + "with People's model"); - configureACL(adminSession); - } - } - - // First draft of configuration of the people specific rights - private void configureACL(Session session) throws RepositoryException { - String memberGroupDn = "cn=" + PeopleConstants.ROLE_MEMBER + ",ou=roles,ou=node"; - JcrUtils.addPrivilege(session, getBasePath(null), memberGroupDn, Privilege.JCR_ALL); - JcrUtils.addPrivilege(session, "/", NodeConstants.ROLE_ADMIN, Privilege.JCR_ALL); - JcrUtils.addPrivilege(session, publicPath, NodeConstants.ROLE_USER, Privilege.JCR_READ); - JcrUtils.addPrivilege(session, publicPath, "anonymous", Privilege.JCR_READ); - JcrUtils.addPrivilege(session, publicPath, NodeConstants.ROLE_ANONYMOUS, Privilege.JCR_READ); - JcrUtils.addPrivilege(session, sharedFilePath, NodeConstants.ROLE_USER, Privilege.JCR_ALL); - session.save(); - log.info("Access control configured"); - } - - /** - * Initialises People resource model and optionally imports legacy resources - */ - protected void initModelResources(Session adminSession) throws RepositoryException { - // initialisation - ResourceService resourceService = getResourceService(); - resourceService.initialiseResources(adminSession); - - // Resource resource = initResources.get("Countries"); - // if (resourceService.getTagLikeResourceParent(adminSession, - // PeopleConstants.RESOURCE_COUNTRY) == null - // && resource != null) { - // resourceService.createTagLikeResourceParent(adminSession, - // PeopleConstants.RESOURCE_COUNTRY, - // PeopleTypes.PEOPLE_TAG_ENCODED_INSTANCE, PeopleNames.PEOPLE_CODE, - // getBasePath(null), - // JcrUiUtils.getLocalJcrItemName(NodeType.NT_UNSTRUCTURED), new - // ArrayList()); - // String EN_SHORT_NAME = "English short name (upper-lower case)"; - // String ISO_CODE = "Alpha-2 code"; - // new EncodedTagCsvFileParser(resourceService, adminSession, - // PeopleConstants.RESOURCE_COUNTRY, ISO_CODE, - // EN_SHORT_NAME).parse(resource.getInputStream(), "UTF-8"); - // } - // - // resource = initResources.get("Languages"); - // if (resourceService.getTagLikeResourceParent(adminSession, - // PeopleConstants.RESOURCE_LANG) == null - // && resource != null) { - // resourceService.createTagLikeResourceParent(adminSession, - // PeopleConstants.RESOURCE_LANG, - // PeopleTypes.PEOPLE_TAG_ENCODED_INSTANCE, PeopleNames.PEOPLE_CODE, - // getBasePath(null), - // JcrUiUtils.getLocalJcrItemName(NodeType.NT_UNSTRUCTURED), new - // ArrayList()); - // String EN_SHORT_NAME = "Language name"; - // String ISO_CODE = "639-1"; - // new EncodedTagCsvFileParser(resourceService, adminSession, - // PeopleConstants.RESOURCE_LANG, ISO_CODE, - // EN_SHORT_NAME).parse(resource.getInputStream(), "UTF-8"); - // } - - // Create tag & mailing list parents - if (resourceService.getTagLikeResourceParent(adminSession, PeopleConstants.RESOURCE_TAG) == null) - resourceService.createTagLikeResourceParent(adminSession, PeopleConstants.RESOURCE_TAG, - PeopleTypes.PEOPLE_TAG_INSTANCE, null, getBasePath(null), PeopleTypes.PEOPLE_ENTITY, - PeopleNames.PEOPLE_TAGS); - if (resourceService.getTagLikeResourceParent(adminSession, PeopleTypes.PEOPLE_MAILING_LIST) == null) - resourceService.createTagLikeResourceParent(adminSession, null, PeopleTypes.PEOPLE_MAILING_LIST, null, - getBasePath(null), PeopleTypes.PEOPLE_ENTITY, PeopleNames.PEOPLE_MAILING_LISTS); - - if (adminSession.hasPendingChanges()) { - adminSession.save(); - log.info("Resources have been added to People's model"); - } - } - - /* DEPENDENCY INJECTION */ - public void setRepository(Repository repository) { - this.repository = repository; - } - - public void setWorkspaceName(String workspaceName) { - this.workspaceName = workspaceName; - } -} diff --git a/org.argeo.suite.web/src/org/argeo/suite/web/DefaultMainPage.java b/org.argeo.suite.web/src/org/argeo/suite/web/DefaultMainPage.java index d1ecbf2..7b3ae2e 100644 --- a/org.argeo.suite.web/src/org/argeo/suite/web/DefaultMainPage.java +++ b/org.argeo.suite.web/src/org/argeo/suite/web/DefaultMainPage.java @@ -21,7 +21,7 @@ import org.argeo.connect.people.PeopleService; import org.argeo.connect.people.PeopleTypes; import org.argeo.connect.people.web.pages.PeopleDefaultPage; import org.argeo.eclipse.ui.EclipseUiUtils; -import org.argeo.suite.fs.MyFilesBrowserPage; +import org.argeo.suite.web.fs.MyFilesBrowserPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; diff --git a/org.argeo.suite.web/src/org/argeo/suite/web/fs/MyFilesBrowserPage.java b/org.argeo.suite.web/src/org/argeo/suite/web/fs/MyFilesBrowserPage.java new file mode 100644 index 0000000..cb4bdba --- /dev/null +++ b/org.argeo.suite.web/src/org/argeo/suite/web/fs/MyFilesBrowserPage.java @@ -0,0 +1,40 @@ +package org.argeo.suite.web.fs; + +import java.nio.file.spi.FileSystemProvider; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; + +import org.argeo.cms.auth.CurrentUser; +import org.argeo.cms.ui.CmsUiProvider; +import org.argeo.cms.ui.fs.CmsFsBrowser; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; + +/** Default file browser page for the CMS */ +public class MyFilesBrowserPage implements CmsUiProvider { + + private FileSystemProvider nodeFileSystemProvider; + + public MyFilesBrowserPage(FileSystemProvider nodeFileSystemProvider) { + this.nodeFileSystemProvider = nodeFileSystemProvider; + } + + @Override + public Control createUi(Composite parent, Node context) throws RepositoryException { + parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); + + if (CurrentUser.isAnonymous()) + // TODO implement public file display + return null; + + CmsFsBrowser browser = new CmsFsBrowser(parent, SWT.NO_FOCUS, context, nodeFileSystemProvider); + browser.setLayoutData(EclipseUiUtils.fillAll()); + + // TODO set input on the default home folder parent for one user's + // files + return browser; + } +} diff --git a/org.argeo.suite.workbench.rap/META-INF/spring/osgi.xml b/org.argeo.suite.workbench.rap/META-INF/spring/osgi.xml index 3f9c473..9b36c03 100644 --- a/org.argeo.suite.workbench.rap/META-INF/spring/osgi.xml +++ b/org.argeo.suite.workbench.rap/META-INF/spring/osgi.xml @@ -12,4 +12,12 @@ + + + + + + + diff --git a/org.argeo.suite.workbench.rap/META-INF/spring/parts.xml b/org.argeo.suite.workbench.rap/META-INF/spring/parts.xml index a5bfde6..f2ae1fd 100644 --- a/org.argeo.suite.workbench.rap/META-INF/spring/parts.xml +++ b/org.argeo.suite.workbench.rap/META-INF/spring/parts.xml @@ -12,6 +12,14 @@ + + + + + + + diff --git a/org.argeo.suite.workbench.rap/bnd.bnd b/org.argeo.suite.workbench.rap/bnd.bnd index 9e3c867..99121fc 100644 --- a/org.argeo.suite.workbench.rap/bnd.bnd +++ b/org.argeo.suite.workbench.rap/bnd.bnd @@ -11,9 +11,11 @@ javax.jcr.nodetype,\ javax.jcr.security,\ org.argeo.cms,\ org.argeo.cms.ui.workbench,\ +org.argeo.connect,\ org.argeo.connect.people.workbench.rap.views,\ org.argeo.connect.ui,\ org.argeo.eclipse.spring,\ org.argeo.node,\ org.argeo.util,\ +org.argeo.cms.ui.workbench.jcr,\ * \ No newline at end of file diff --git a/org.argeo.suite.workbench.rap/plugin.xml b/org.argeo.suite.workbench.rap/plugin.xml index 5315b88..bdc6808 100644 --- a/org.argeo.suite.workbench.rap/plugin.xml +++ b/org.argeo.suite.workbench.rap/plugin.xml @@ -33,6 +33,13 @@ name="Test View" restorable="true"> + + diff --git a/org.argeo.suite.workbench.rap/pom.xml b/org.argeo.suite.workbench.rap/pom.xml index df9f8cd..d6ec915 100644 --- a/org.argeo.suite.workbench.rap/pom.xml +++ b/org.argeo.suite.workbench.rap/pom.xml @@ -14,7 +14,7 @@ org.argeo.suite - org.argeo.suite.web + org.argeo.suite.core 0.1.1-SNAPSHOT diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/DashboardPerspective.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/DashboardPerspective.java index edf357a..f723e8d 100644 --- a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/DashboardPerspective.java +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/DashboardPerspective.java @@ -1,8 +1,8 @@ package org.argeo.suite.workbench; -import org.argeo.cms.ui.workbench.jcr.NodeFsBrowserView; import org.argeo.connect.people.workbench.rap.views.MyTasksView; import org.argeo.connect.people.workbench.rap.views.QuickSearchView; +import org.argeo.suite.workbench.parts.MyFilesView; import org.eclipse.ui.IFolderLayout; import org.eclipse.ui.IPageLayout; import org.eclipse.ui.IPerspectiveFactory; @@ -15,11 +15,11 @@ public class DashboardPerspective implements IPerspectiveFactory { layout.setEditorAreaVisible(true); layout.setFixed(false); - IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.33f, editorArea); + IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.25f, editorArea); // Only show contacts if current user is a coworker // if (CurrentUser.isInRole(Role.coworker.dn())) left.addView(MyTasksView.ID); left.addView(QuickSearchView.ID); - left.addView(NodeFsBrowserView.ID); + left.addView(MyFilesView.ID); } } diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsAppService.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsAppService.java new file mode 100644 index 0000000..fc9563d --- /dev/null +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsAppService.java @@ -0,0 +1,70 @@ +package org.argeo.suite.workbench.fs; + +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.FileSystem; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.spi.FileSystemProvider; +import java.security.PrivilegedActionException; + +import javax.jcr.Session; + +import org.argeo.cms.auth.CurrentUser; +import org.argeo.node.NodeUtils; +import org.argeo.suite.SuiteException; + +public class FsAppService { + private final static String NODE_PREFIX = "node://"; + + private String getCurrentHomePath(Session session) { + try { + // Make in a do as if not from the workbench + // Repository repo = session.getRepository(); + // session = CurrentUser.tryAs(() -> repo.login()); + String homepath = NodeUtils.getUserHome(session).getPath(); + return homepath; + } catch (Exception e) { + throw new SuiteException("Cannot retrieve Current User Home Path", e); + // } finally { + // JcrUtils.logoutQuietly(session); + } + } + + public Path[] getMyFilesPath(FileSystemProvider nodeFileSystemProvider, Session session) { + // return Paths.get(System.getProperty("user.dir")); + String currHomeUriStr = NODE_PREFIX + getCurrentHomePath(session); + try { + URI uri = new URI(currHomeUriStr); + FileSystem fileSystem = nodeFileSystemProvider.getFileSystem(uri); + if (fileSystem == null) { + fileSystem = CurrentUser.tryAs(() -> nodeFileSystemProvider.newFileSystem(uri, null)); + // PrivilegedExceptionAction pea = new + // PrivilegedExceptionAction() { + // @Override + // public FileSystem run() throws Exception { + // return nodeFileSystemProvider.newFileSystem(uri, null); + // } + // + // }; + // fileSystem = CurrentUser.tryAs(pea); + } + Path[] paths = { fileSystem.getPath(getCurrentHomePath(session)), fileSystem.getPath("/") }; + return paths; + } catch (URISyntaxException | PrivilegedActionException e) { + throw new RuntimeException("unable to initialise home file system for " + currHomeUriStr, e); + } + } + + public Path[] getMyGroupsFilesPath(FileSystemProvider nodeFileSystemProvider, Session session) { + // TODO + Path[] paths = { Paths.get(System.getProperty("user.dir")), Paths.get("/tmp") }; + return paths; + } + + public Path[] getMyBookmarks(FileSystemProvider nodeFileSystemProvider, Session session) { + // TODO + Path[] paths = { Paths.get(System.getProperty("user.dir")), Paths.get("/tmp"), Paths.get("/opt") }; + return paths; + } +} diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsImages.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsImages.java new file mode 100644 index 0000000..ec6304f --- /dev/null +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsImages.java @@ -0,0 +1,12 @@ +package org.argeo.suite.workbench.fs; + +import org.argeo.suite.workbench.AsUiPlugin; +import org.eclipse.swt.graphics.Image; + +/** Shared icons for the file system RAP workbench */ +public class FsImages { + final private static String BASE_PATH = "/theme/argeo-classic/icons/fs/"; + // Various types + public final static Image ICON_FOLDER = AsUiPlugin.getImageDescriptor(BASE_PATH + "folder.gif").createImage(); + public final static Image ICON_FILE = AsUiPlugin.getImageDescriptor(BASE_PATH + "file.gif").createImage(); +} diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsSingleColumnLabelProvider.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsSingleColumnLabelProvider.java new file mode 100644 index 0000000..d3c62ff --- /dev/null +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/fs/FsSingleColumnLabelProvider.java @@ -0,0 +1,56 @@ +package org.argeo.suite.workbench.fs; + +import javax.jcr.Node; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NodeType; + +import org.argeo.connect.people.PeopleNames; +import org.argeo.connect.ui.ConnectUiUtils; +import org.argeo.suite.SuiteException; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.graphics.Image; + +/** + * Provide a single column label provider for file and directory lists. Icon and + * displayed text vary with the element node type + */ +public class FsSingleColumnLabelProvider extends LabelProvider implements PeopleNames { + private static final long serialVersionUID = -8895136766988459632L; + + public FsSingleColumnLabelProvider() { + } + + @Override + public String getText(Object element) { + try { + Node entity = (Node) element; + String result; + if (entity.isNodeType(NodeType.NT_FILE)) + result = entity.getName(); + // result = ConnectJcrUtils.get(entity, Property.JCR_TITLE); + else if (entity.isNodeType(NodeType.NT_FOLDER)) + result = entity.getName(); + // result = ConnectJcrUtils.get(entity, Property.JCR_TITLE); + else + result = ""; + return ConnectUiUtils.replaceAmpersand(result); + } catch (RepositoryException re) { + throw new SuiteException("Unable to get formatted value for node", re); + } + } + + /** Overwrite this method to provide project specific images */ + @Override + public Image getImage(Object element) { + try { + Node entity = (Node) element; + if (entity.isNodeType(NodeType.NT_FILE)) + return FsImages.ICON_FILE; + else if (entity.isNodeType(NodeType.NT_FOLDER)) + return FsImages.ICON_FOLDER; + return null; + } catch (RepositoryException re) { + throw new SuiteException("Cannot get icon for " + element, re); + } + } +} diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java index 052d2c6..cfbe2ee 100644 --- a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/DefaultDashboardEditor.java @@ -1,9 +1,13 @@ package org.argeo.suite.workbench.parts; +import javax.jcr.Node; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.argeo.connect.people.PeopleConstants; import org.argeo.connect.people.PeopleTypes; import org.argeo.connect.people.workbench.rap.PeopleRapUtils; +import org.argeo.connect.util.ConnectJcrUtils; import org.argeo.eclipse.ui.EclipseUiUtils; import org.argeo.suite.workbench.AsUiPlugin; import org.eclipse.swt.SWT; @@ -73,10 +77,26 @@ public class DefaultDashboardEditor extends AbstractSuiteDashboard { parent.setLayout(EclipseUiUtils.noSpaceGridLayout()); createGadgetTitleCmp(parent, "Contacts"); Composite bodyCmp = createGadgetBodyCmp(parent); + PeopleRapUtils.createOpenSearchEditorLink(getPeopleWorkbenchService(), bodyCmp, "Persons", PeopleTypes.PEOPLE_PERSON, getPeopleService().getBasePath(PeopleTypes.PEOPLE_PERSON)); PeopleRapUtils.createOpenSearchEditorLink(getPeopleWorkbenchService(), bodyCmp, "Organisations", PeopleTypes.PEOPLE_ORG, getPeopleService().getBasePath(PeopleTypes.PEOPLE_ORG)); + + Node tagParent = getPeopleService().getResourceService().getTagLikeResourceParent(getSession(), + PeopleTypes.PEOPLE_MAILING_LIST); + PeopleRapUtils.createOpenSearchEditorLink(getPeopleWorkbenchService(), bodyCmp, "Mailing lists", + PeopleTypes.PEOPLE_MAILING_LIST, ConnectJcrUtils.getPath(tagParent)); + + PeopleRapUtils.createOpenSearchEditorLink(getPeopleWorkbenchService(), bodyCmp, "Tasks", + PeopleTypes.PEOPLE_TASK, getPeopleService().getBasePath(null)); + + tagParent = getPeopleService().getResourceService().getTagLikeResourceParent(getSession(), + PeopleConstants.RESOURCE_TAG); + + PeopleRapUtils.createOpenSearchEditorLink(getPeopleWorkbenchService(), bodyCmp, "Tags", + PeopleTypes.PEOPLE_TAG_INSTANCE, ConnectJcrUtils.getPath(tagParent)); + } } diff --git a/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/MyFilesView.java b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/MyFilesView.java new file mode 100644 index 0000000..d89a228 --- /dev/null +++ b/org.argeo.suite.workbench.rap/src/org/argeo/suite/workbench/parts/MyFilesView.java @@ -0,0 +1,293 @@ +/* + * Copyright (C) 2007-2012 Argeo GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.argeo.suite.workbench.parts; + +import static org.argeo.eclipse.ui.EclipseUiUtils.notEmpty; + +import java.nio.file.spi.FileSystemProvider; + +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.nodetype.NodeType; +import javax.jcr.query.Query; +import javax.jcr.query.QueryManager; +import javax.jcr.query.QueryResult; + +import org.argeo.cms.util.CmsUtils; +import org.argeo.connect.ConnectConstants; +import org.argeo.connect.people.PeopleException; +import org.argeo.connect.people.workbench.rap.providers.BasicNodeListContentProvider; +import org.argeo.connect.ui.ConnectUiConstants; +import org.argeo.connect.ui.widgets.DelayedText; +import org.argeo.connect.util.ConnectJcrUtils; +import org.argeo.connect.util.XPathUtils; +import org.argeo.eclipse.ui.EclipseUiUtils; +import org.argeo.eclipse.ui.fs.FsTableViewer; +import org.argeo.jcr.JcrUtils; +import org.argeo.suite.workbench.AsUiPlugin; +import org.argeo.suite.workbench.fs.FsAppService; +import org.argeo.suite.workbench.fs.FsSingleColumnLabelProvider; +import org.eclipse.jface.layout.TableColumnLayout; +import org.eclipse.jface.viewers.ColumnWeightData; +import org.eclipse.jface.viewers.DoubleClickEvent; +import org.eclipse.jface.viewers.IDoubleClickListener; +import org.eclipse.jface.viewers.ILabelProvider; +import org.eclipse.jface.viewers.IStructuredSelection; +import org.eclipse.jface.viewers.StructuredSelection; +import org.eclipse.jface.viewers.TableViewer; +import org.eclipse.rap.rwt.service.ServerPushSession; +import org.eclipse.swt.SWT; +import org.eclipse.swt.events.KeyEvent; +import org.eclipse.swt.events.KeyListener; +import org.eclipse.swt.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.layout.GridData; +import org.eclipse.swt.layout.GridLayout; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Label; +import org.eclipse.swt.widgets.Table; +import org.eclipse.swt.widgets.TableColumn; +import org.eclipse.ui.part.ViewPart; + +/** Browse the node file system. */ +public class MyFilesView extends ViewPart implements IDoubleClickListener { + public final static String ID = AsUiPlugin.PLUGIN_ID + ".myFilesView"; + + private FileSystemProvider nodeFileSystemProvider; + private FsAppService fsAppService; + private Repository repository; + private Session session; + + private DelayedText filterTxt; + private TableViewer searchResultsViewer; + private Composite searchCmp; + + @Override + public void createPartControl(Composite parent) { + session = ConnectJcrUtils.login(repository); + // MainLayout + parent.setLayout(new GridLayout()); + addFilterPanel(parent); + searchCmp = new Composite(parent, SWT.NO_FOCUS); + searchCmp.setLayout(EclipseUiUtils.noSpaceGridLayout()); + searchResultsViewer = createListPart(searchCmp, new FsSingleColumnLabelProvider()); + GridData gd = EclipseUiUtils.fillWidth(); + gd.heightHint = 0; + searchCmp.setLayoutData(gd); + + Composite bookmarkCmp = new Composite(parent, SWT.NO_FOCUS); + bookmarkCmp.setLayoutData(EclipseUiUtils.fillAll()); + populateBookmarks(bookmarkCmp); + } + + public void addFilterPanel(Composite parent) { + // Use a delayed text: the query won't be done until the user stop + // typing for 800ms + int style = SWT.BORDER | SWT.SEARCH | SWT.ICON_CANCEL; + filterTxt = new DelayedText(parent, style, ConnectUiConstants.SEARCH_TEXT_DELAY); + filterTxt.setLayoutData(EclipseUiUtils.fillWidth()); + + final ServerPushSession pushSession = new ServerPushSession(); + filterTxt.addDelayedModifyListener(pushSession, new ModifyListener() { + private static final long serialVersionUID = 5003010530960334977L; + + public void modifyText(ModifyEvent event) { + filterTxt.getDisplay().asyncExec(new Runnable() { + @Override + public void run() { + int resultNb = refreshFilteredList(); + if (resultNb > 0) + ((GridData) searchCmp.getLayoutData()).heightHint = 120; + else + ((GridData) searchCmp.getLayoutData()).heightHint = 0; + parent.layout(true, true); + } + }); + pushSession.stop(); + } + }); + + // Jump to the first item of the list using the down arrow + filterTxt.addKeyListener(new KeyListener() { + private static final long serialVersionUID = -4523394262771183968L; + + @Override + public void keyReleased(KeyEvent e) { + } + + @Override + public void keyPressed(KeyEvent e) { + // boolean shiftPressed = (e.stateMask & SWT.SHIFT) != 0; + // boolean altPressed = (e.stateMask & SWT.ALT) != 0; + if (e.keyCode == SWT.ARROW_DOWN || e.keyCode == SWT.TAB) { + Object first = searchResultsViewer.getElementAt(0); + if (first != null) { + searchResultsViewer.getTable().setFocus(); + searchResultsViewer.setSelection(new StructuredSelection(first), true); + } + e.doit = false; + } + } + }); + } + + protected TableViewer createListPart(Composite parent, ILabelProvider labelProvider) { + parent.setLayout(new GridLayout()); + + Composite tableComposite = new Composite(parent, SWT.NONE); + GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_VERTICAL + | GridData.VERTICAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL); + tableComposite.setLayoutData(gd); + + TableViewer v = new TableViewer(tableComposite); + v.setLabelProvider(labelProvider); + + TableColumn singleColumn = new TableColumn(v.getTable(), SWT.V_SCROLL); + TableColumnLayout tableColumnLayout = new TableColumnLayout(); + tableColumnLayout.setColumnData(singleColumn, new ColumnWeightData(85)); + tableComposite.setLayout(tableColumnLayout); + + // Corresponding table & style + Table table = v.getTable(); + table.setLinesVisible(true); + table.setHeaderVisible(false); + CmsUtils.markup(table); + CmsUtils.setItemHeight(table, 26); + + v.setContentProvider(new BasicNodeListContentProvider()); + v.addDoubleClickListener(this); + return v; + } + + @Override + public void dispose() { + JcrUtils.logoutQuietly(session); + super.dispose(); + } + + protected int refreshFilteredList() { + try { + String filter = filterTxt.getText(); + // Prevents the query on the full repository + if (EclipseUiUtils.isEmpty(filter)) { + searchResultsViewer.setInput(null); + return 0; + } + + QueryManager queryManager = session.getWorkspace().getQueryManager(); + + // XPATH Query + // TODO manage cleanly jcr: prefix + // String xpathQueryStr = "//element(*, " + NodeType.NT_FILE + ")"; + String xpathQueryStr = "//element(*, nt:file)"; + String xpathFilter = XPathUtils.getFreeTextConstraint(filter); + if (notEmpty(xpathFilter)) + xpathQueryStr += "[" + xpathFilter + "]"; + + Query xpathQuery = queryManager.createQuery(xpathQueryStr, ConnectConstants.QUERY_XPATH); + + // xpathQuery.setLimit(TrackerUiConstants.SEARCH_DEFAULT_LIMIT); + QueryResult result = xpathQuery.execute(); + + NodeIterator nit = result.getNodes(); + searchResultsViewer.setInput(JcrUtils.nodeIteratorToList(nit)); + + return (int) nit.getSize(); + } catch (RepositoryException e) { + throw new PeopleException("Unable to list files", e); + } + } + + private void populateBookmarks(Composite parent) { + CmsUtils.clear(parent); + parent.setLayout(new GridLayout()); + + int bookmarkColWith = 200; + + FsTableViewer homeViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL); + Table table = homeViewer.configureDefaultSingleColumnTable(bookmarkColWith); + GridData gd = EclipseUiUtils.fillWidth(); + gd.horizontalIndent = 10; + table.setLayoutData(gd); + homeViewer.addDoubleClickListener(this); + homeViewer.setPathsInput(fsAppService.getMyFilesPath(nodeFileSystemProvider, session)); + + appendTitle(parent, "Shared files"); + FsTableViewer groupsViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL); + table = groupsViewer.configureDefaultSingleColumnTable(bookmarkColWith); + gd = EclipseUiUtils.fillWidth(); + gd.horizontalIndent = 10; + table.setLayoutData(gd); + groupsViewer.addDoubleClickListener(this); + groupsViewer.setPathsInput(fsAppService.getMyGroupsFilesPath(nodeFileSystemProvider, session)); + + appendTitle(parent, "My bookmarks"); + FsTableViewer bookmarksViewer = new FsTableViewer(parent, SWT.SINGLE | SWT.NO_SCROLL); + table = bookmarksViewer.configureDefaultSingleColumnTable(bookmarkColWith); + gd = EclipseUiUtils.fillWidth(); + gd.horizontalIndent = 10; + table.setLayoutData(gd); + bookmarksViewer.addDoubleClickListener(this); + bookmarksViewer.setPathsInput(fsAppService.getMyBookmarks(nodeFileSystemProvider, session)); + } + + private Label appendTitle(Composite parent, String value) { + Label titleLbl = new Label(parent, SWT.NONE); + titleLbl.setText(value); + titleLbl.setFont(EclipseUiUtils.getBoldFont(parent)); + GridData gd = EclipseUiUtils.fillWidth(); + gd.horizontalIndent = 5; + gd.verticalIndent = 5; + titleLbl.setLayoutData(gd); + return titleLbl; + } + + @Override + public void doubleClick(DoubleClickEvent event) { + IStructuredSelection selection = (IStructuredSelection) event.getSelection(); + if (selection.isEmpty()) + return; + else { + System.out.println("Double clicked"); + // TODO open corresponding editor + // Path newSelected = (Path) selection.getFirstElement(); + // if (newSelected.equals(currDisplayedFolder) && + // newSelected.equals(initialPath)) + // return; + // initialPath = newSelected; + // setInput(newSelected); + } + } + + @Override + public void setFocus() { + } + + /* DEPENDENCY INJECTION */ + public void setRepository(Repository repository) { + this.repository = repository; + } + + public void setNodeFileSystemProvider(FileSystemProvider nodeFileSystemProvider) { + this.nodeFileSystemProvider = nodeFileSystemProvider; + } + + public void setFsAppService(FsAppService fsAppService) { + this.fsAppService = fsAppService; + } +} diff --git a/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/file.gif b/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/file.gif new file mode 100644 index 0000000..ef30288 Binary files /dev/null and b/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/file.gif differ diff --git a/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/folder.gif b/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/folder.gif new file mode 100644 index 0000000..42e027c Binary files /dev/null and b/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/folder.gif differ diff --git a/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/fsBrowser.png b/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/fsBrowser.png new file mode 100644 index 0000000..3f56074 Binary files /dev/null and b/org.argeo.suite.workbench.rap/theme/argeo-classic/icons/fs/fsBrowser.png differ diff --git a/pom.xml b/pom.xml index f743512..14d4581 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,7 @@ 0.1.1-SNAPSHOT + org.argeo.suite.core org.argeo.suite.web org.argeo.suite.workbench.rap sdk