From 22e59525f870a2ce5b302bcd43dfeb54313b6f8f Mon Sep 17 00:00:00 2001
From: pkupczyk <pkupczyk>
Date: Tue, 13 Nov 2012 08:56:00 +0000
Subject: [PATCH] SP-385 / BIS-247 : Metaprojects Browsing and Maintenance UI -
 initial version of the metaproject tree

SVN: 27583
---
 .../web/client/ICommonClientService.java      |  15 +
 .../web/client/ICommonClientServiceAsync.java |  15 +
 .../client/web/client/application/Dict.java   |  18 +
 .../framework/ComponentProvider.java          |  39 ++
 .../application/help/HelpPageIdentifier.java  |   2 +
 .../web/client/application/menu/TopMenu.java  |   8 +-
 .../application/menu/top/BrowseMenu.java      |   3 +
 .../experiment/MetaprojectBrowserGrids.java   |  55 +++
 .../ui/field/MetaprojectChooserButton.java    |   2 +-
 .../ui/grid/DisposableComposite.java          |  94 ++++
 .../browser/MetaprojectBrowser.java           | 102 +++++
 .../browser/MetaprojectBrowserTree.java       |  76 ++++
 .../{ => grid}/MetaprojectGrid.java           |   2 +-
 .../ui/metaproject/tree/MetaprojectTree.java  | 403 ++++++++++++++++++
 .../model/MetaprojectTreeEntityItemData.java  |  76 ++++
 .../MetaprojectTreeEntityKindItemData.java    |  84 ++++
 .../tree/model/MetaprojectTreeItemData.java   |  29 ++
 .../MetaprojectTreeMetaprojectItemData.java   |  66 +++
 .../MetaprojectTreeEntityItemWidget.java      |  59 +++
 .../MetaprojectTreeEntityKindItemWidget.java  |  39 ++
 .../widget/MetaprojectTreeItemWidget.java     |  62 +++
 .../MetaprojectTreeMetaprojectItemWidget.java |  81 ++++
 .../web/server/CommonClientService.java       |  29 ++
 .../openbis/generic/server/CommonServer.java  | 100 ++++-
 .../generic/server/CommonServerLogger.java    |  22 +-
 .../server/dataaccess/IMetaprojectDAO.java    |  13 +
 .../server/dataaccess/db/MetaprojectDAO.java  |  43 ++
 .../openbis/generic/shared/ICommonServer.java |  18 +-
 .../dto/MetaprojectAssignmentsCount.java      |  89 ++++
 .../MetaprojectAssignmentsFetchOption.java    |  27 ++
 .../cisd/openbis/public/common-dictionary.js  |  17 +
 31 files changed, 1664 insertions(+), 24 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/MetaprojectBrowserGrids.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComposite.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowser.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowserTree.java
 rename openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/{ => grid}/MetaprojectGrid.java (99%)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/MetaprojectTree.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityItemData.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityKindItemData.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeItemData.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeMetaprojectItemData.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityItemWidget.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityKindItemWidget.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeItemWidget.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeMetaprojectItemWidget.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsCount.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsFetchOption.java

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
index 433c4ce4ca8..1698ab9ce62 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientService.java
@@ -90,6 +90,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
@@ -159,6 +162,18 @@ public interface ICommonClientService extends IClientService
     public TypedTableResultSet<Metaproject> listMetaprojects(ListMetaprojectsCriteria criteria)
             throws UserFailureException;
 
+    /**
+     * Returns a list of all metaproject assignment counts.
+     */
+    public List<MetaprojectAssignmentsCount> listMetaprojectAssignmentsCounts()
+            throws UserFailureException;
+
+    /**
+     * Returns metaproject assignments.
+     */
+    public MetaprojectAssignments getMetaprojectAssignments(Long metaprojectId,
+            MetaprojectAssignmentsFetchOption[] fetchOptions) throws UserFailureException;
+
     /**
      * Like {@link #prepareExportSamples(TableExportCriteria)}, but for scripts.
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
index 7bda8c87206..644fe4c24cc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/ICommonClientServiceAsync.java
@@ -92,6 +92,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
@@ -143,6 +146,18 @@ public interface ICommonClientServiceAsync extends IClientServiceAsync
     public void listMetaprojects(ListMetaprojectsCriteria criteria,
             final AsyncCallback<TypedTableResultSet<Metaproject>> asyncCallback);
 
+    /** @see ICommonClientService#listMetaprojectAssignmentsCounts() */
+    public void listMetaprojectAssignmentsCounts(
+            final AsyncCallback<List<MetaprojectAssignmentsCount>> asyncCallback);
+
+    /**
+     * @see ICommonClientService#getMetaprojectAssignments(Long,
+     *      MetaprojectAssignmentsFetchOption[])
+     */
+    public void getMetaprojectAssignments(Long metaprojectId,
+            MetaprojectAssignmentsFetchOption[] fetchOptions,
+            final AsyncCallback<MetaprojectAssignments> asyncCallback);
+
     /** @see ICommonClientService#prepareExportScripts(TableExportCriteria) */
     public void prepareExportScripts(
             TableExportCriteria<TableModelRowWithObject<Script>> exportCriteria,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
index de33dd5e361..879ad557054 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/Dict.java
@@ -950,6 +950,24 @@ public abstract class Dict
     //
     public static final String PROJECT_REGISTRATION = "project_registration";
 
+    //
+    // Metaproject Tree
+    //
+
+    public static final String METAPROJECT_TREE_COLUMN_HEADER = "metaproject_tree_column_header";
+
+    public static final String METAPROJECT_TREE_INFO_LINK = "metaproject_tree_info_link";
+
+    //
+    // Metaproject Browser
+    //
+    public static final String METAPROJECT_BROWSER = "metaproject_browser";
+
+    public static final String METAPROJECT_BROWSER_TREE_TITLE = "metaproject_browser_tree_title";
+
+    public static final String METAPROJECT_BROWSER_TREE_TOOLTIP =
+            "metaproject_browser_tree_tooltip";
+
     //
     // Detailed Search
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
index bd888a95d8f..e237ea8f17f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/framework/ComponentProvider.java
@@ -48,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ID
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.MaterialBatchRegistrationUpdatePanel;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.MaterialBrowserGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.material.MaterialTypeGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.browser.MetaprojectBrowser;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.project.ProjectGrid;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.project.ProjectRegistrationForm;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.property_type.PropertyTypeAssignmentForm;
@@ -975,6 +976,44 @@ public final class ComponentProvider
             };
     }
 
+    public final AbstractTabItemFactory getMetaprojectBrowser()
+    {
+        return new AbstractTabItemFactory()
+            {
+                @Override
+                public ITabItem create()
+                {
+                    IDisposableComponent browser = new MetaprojectBrowser(viewContext);
+                    return createTab(getTabTitle(), browser);
+                }
+
+                @Override
+                public String getId()
+                {
+                    return MetaprojectBrowser.ID;
+                }
+
+                @Override
+                public HelpPageIdentifier getHelpPageIdentifier()
+                {
+                    return new HelpPageIdentifier(HelpPageDomain.METAPROJECT, HelpPageAction.BROWSE);
+                }
+
+                @Override
+                public String getTabTitle()
+                {
+                    return getMessage(Dict.METAPROJECT_BROWSER);
+                }
+
+                @Override
+                public String tryGetLink()
+                {
+                    return null;
+                }
+
+            };
+    }
+
     public final AbstractTabItemFactory getDeletionBrowser()
     {
         return new AbstractTabItemFactory()
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java
index a899e537580..9795ffb0c46 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/help/HelpPageIdentifier.java
@@ -51,6 +51,8 @@ public class HelpPageIdentifier
 
         PROJECT(ADMINISTRATION),
 
+        METAPROJECT(ADMINISTRATION),
+
         VOCABULARY(ADMINISTRATION),
         // vocabulary subdomains
         TERM(VOCABULARY),
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java
index 2e6566fc92a..4959fac65f1 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/TopMenu.java
@@ -50,10 +50,8 @@ public class TopMenu extends LayoutContainer
     /** {@link ActionMenu} kind enum with names matching dictionary keys */
     public static enum ActionMenuKind implements IActionMenuItem
     {
-        ADMINISTRATION_MENU_MANAGE_GROUPS,
-        ADMINISTRATION_MENU_MANAGE_TYPES,
-        ADMINISTRATION_MENU_MANAGE_PROPERTY_TYPES,
-        ADMINISTRATION_MENU_MANAGE_AUTHORIZATION,
+        ADMINISTRATION_MENU_MANAGE_GROUPS, ADMINISTRATION_MENU_MANAGE_TYPES,
+        ADMINISTRATION_MENU_MANAGE_PROPERTY_TYPES, ADMINISTRATION_MENU_MANAGE_AUTHORIZATION,
 
         AUTHORIZATION_MENU_USERS, AUTHORIZATION_MENU_ROLES,
         AUTHORIZATION_MENU_AUTHORIZATION_GROUPS,
@@ -75,6 +73,8 @@ public class TopMenu extends LayoutContainer
 
         PROJECT_MENU_BROWSE, PROJECT_MENU_NEW,
 
+        METAPROJECT_MENU_BROWSE,
+
         PROPERTY_TYPES_MENU_BROWSE_PROPERTY_TYPES, PROPERTY_TYPES_MENU_BROWSE_ASSIGNMENTS,
         PROPERTY_TYPES_MENU_NEW_PROPERTY_TYPES, PROPERTY_TYPES_MENU_ASSIGN_TO_EXPERIMENT_TYPE,
         PROPERTY_TYPES_MENU_ASSIGN_TO_MATERIAL_TYPE, PROPERTY_TYPES_MENU_ASSIGN_TO_DATA_SET_TYPE,
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/BrowseMenu.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/BrowseMenu.java
index 0a1ba6c5558..bfc6a31c5a6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/BrowseMenu.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/menu/top/BrowseMenu.java
@@ -50,6 +50,9 @@ public class BrowseMenu extends TopMenuItem
                 componentProvider.getDataSetSearch()));
         submenu.add(new ActionMenu(TopMenu.ActionMenuKind.MATERIAL_MENU_BROWSE, messageProvider,
                 componentProvider.getMaterialBrowser()));
+        submenu.add(new ActionMenu(TopMenu.ActionMenuKind.METAPROJECT_MENU_BROWSE, messageProvider,
+                componentProvider.getMetaprojectBrowser()));
+
         setMenu(submenu);
     }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/MetaprojectBrowserGrids.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/MetaprojectBrowserGrids.java
new file mode 100644
index 00000000000..8add1dce6be
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/MetaprojectBrowserGrids.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment;
+
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.widget.Composite;
+import com.extjs.gxt.ui.client.widget.Text;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectBrowserGrids extends Composite implements IDisposableComponent
+{
+
+    public MetaprojectBrowserGrids(IViewContext<?> viewContext)
+    {
+        initComponent(new Text("grids"));
+    }
+
+    @Override
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+    }
+
+    @Override
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return null;
+    }
+
+    @Override
+    public void dispose()
+    {
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MetaprojectChooserButton.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MetaprojectChooserButton.java
index 47d6afa993d..38feba55f10 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MetaprojectChooserButton.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/field/MetaprojectChooserButton.java
@@ -28,7 +28,7 @@ import com.extjs.gxt.ui.client.widget.form.Field;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableEntityChooser;
-import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.MetaprojectGrid;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.grid.MetaprojectGrid;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.TableModelRowWithObject;
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComposite.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComposite.java
new file mode 100644
index 00000000000..d0f924e3e80
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/DisposableComposite.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.widget.Component;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.framework.IDatabaseModificationObserver;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.SetUtils;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * @author pkupczyk
+ */
+public class DisposableComposite implements IDisposableComponent
+{
+
+    private Component mainComponent;
+
+    private IDisposableComponent[] subComponents;
+
+    public DisposableComposite(Component mainComponent, IDisposableComponent... subComponents)
+    {
+        this.mainComponent = mainComponent;
+
+        if (subComponents == null)
+        {
+            this.subComponents = new IDisposableComponent[0];
+        } else
+        {
+            this.subComponents = subComponents;
+        }
+
+    }
+
+    @Override
+    public Component getComponent()
+    {
+        return mainComponent;
+    }
+
+    @Override
+    public void dispose()
+    {
+        for (IDisposableComponent subComponent : subComponents)
+        {
+            subComponent.dispose();
+        }
+    }
+
+    @Override
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        Set<DatabaseModificationKind> relevantModifications =
+                new HashSet<DatabaseModificationKind>();
+
+        for (IDisposableComponent subComponent : subComponents)
+        {
+            SetUtils.addAll(relevantModifications, subComponent.getRelevantModifications());
+        }
+
+        return relevantModifications.toArray(DatabaseModificationKind.EMPTY_ARRAY);
+    }
+
+    @Override
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        for (IDatabaseModificationObserver subComponent : subComponents)
+        {
+            if (SetUtils
+                    .containsAny(observedModifications, subComponent.getRelevantModifications()))
+            {
+                subComponent.update(observedModifications);
+            }
+        }
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowser.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowser.java
new file mode 100644
index 00000000000..bec3717cb1e
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowser.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.browser;
+
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.Style.LayoutRegion;
+import com.extjs.gxt.ui.client.util.Margins;
+import com.extjs.gxt.ui.client.widget.Component;
+import com.extjs.gxt.ui.client.widget.ContentPanel;
+import com.extjs.gxt.ui.client.widget.layout.BorderLayout;
+import com.extjs.gxt.ui.client.widget.layout.BorderLayoutData;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.experiment.MetaprojectBrowserGrids;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.DisposableComposite;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectBrowser extends ContentPanel implements IDisposableComponent
+{
+
+    public static final String ID = GenericConstants.ID_PREFIX + "metaproject-browser";
+
+    private MetaprojectBrowserTree tree;
+
+    private MetaprojectBrowserGrids grids;
+
+    private DisposableComposite composite;
+
+    public MetaprojectBrowser(final IViewContext<?> viewContext)
+    {
+        setId(ID);
+        setLayout(new BorderLayout());
+
+        tree = new MetaprojectBrowserTree(viewContext);
+        // GWTUtils.setToolTip(tree, viewContext.getMessage(Dict.METAPROJECT_BROWSER_TREE_TOOLTIP));
+
+        grids = new MetaprojectBrowserGrids(viewContext);
+        composite = new DisposableComposite(this, tree, grids);
+
+        BorderLayoutData treeLayout = new BorderLayoutData(LayoutRegion.WEST, 200, 20, 2000);
+        treeLayout.setSplit(true);
+        treeLayout.setMargins(new Margins(2));
+        treeLayout.setCollapsible(true);
+        treeLayout.setFloatable(false);
+
+        BorderLayoutData gridsLayout = new BorderLayoutData(LayoutRegion.CENTER, 200, 20, 2000);
+        gridsLayout.setSplit(true);
+        gridsLayout.setMargins(new Margins(2));
+        gridsLayout.setCollapsible(true);
+        gridsLayout.setFloatable(false);
+
+        add(tree, treeLayout);
+        add(grids, gridsLayout);
+
+        layout();
+    }
+
+    @Override
+    public Component getComponent()
+    {
+        return composite.getComponent();
+    }
+
+    @Override
+    public void dispose()
+    {
+        composite.dispose();
+    }
+
+    @Override
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return composite.getRelevantModifications();
+    }
+
+    @Override
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+        composite.update(observedModifications);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowserTree.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowserTree.java
new file mode 100644
index 00000000000..62e53c36bae
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/browser/MetaprojectBrowserTree.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2008 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.browser;
+
+import java.util.Set;
+
+import com.extjs.gxt.ui.client.widget.Component;
+import com.extjs.gxt.ui.client.widget.ContentPanel;
+import com.extjs.gxt.ui.client.widget.layout.FitLayout;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.MetaprojectTree;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+
+/**
+ * @author pkupczyk
+ */
+public final class MetaprojectBrowserTree extends ContentPanel implements IDisposableComponent
+{
+
+    public static final String ID = GenericConstants.ID_PREFIX + "metaproject-browser-tree-panel";
+
+    private final MetaprojectTree tree;
+
+    public MetaprojectBrowserTree(final IViewContext<?> viewContext)
+    {
+        setLayout(new FitLayout());
+        setBodyBorder(false);
+        setHeading(viewContext.getMessage(Dict.METAPROJECT_BROWSER_TREE_TITLE));
+
+        tree = new MetaprojectTree(viewContext);
+        add(tree);
+    }
+
+    @Override
+    public void update(Set<DatabaseModificationKind> observedModifications)
+    {
+
+    }
+
+    @Override
+    public DatabaseModificationKind[] getRelevantModifications()
+    {
+        return null;
+    }
+
+    @Override
+    public Component getComponent()
+    {
+        return null;
+    }
+
+    @Override
+    public void dispose()
+    {
+
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/MetaprojectGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/grid/MetaprojectGrid.java
similarity index 99%
rename from openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/MetaprojectGrid.java
rename to openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/grid/MetaprojectGrid.java
index b217957202a..163813e2a67 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/MetaprojectGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/grid/MetaprojectGrid.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject;
+package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.grid;
 
 import java.util.Arrays;
 import java.util.HashSet;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/MetaprojectTree.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/MetaprojectTree.java
new file mode 100644
index 00000000000..342cc90fcd4
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/MetaprojectTree.java
@@ -0,0 +1,403 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import com.extjs.gxt.ui.client.Style.SelectionMode;
+import com.extjs.gxt.ui.client.data.BaseTreeLoader;
+import com.extjs.gxt.ui.client.data.RpcProxy;
+import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
+import com.extjs.gxt.ui.client.event.SelectionChangedListener;
+import com.extjs.gxt.ui.client.store.ListStore;
+import com.extjs.gxt.ui.client.store.TreeStore;
+import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
+import com.extjs.gxt.ui.client.widget.grid.ColumnData;
+import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
+import com.extjs.gxt.ui.client.widget.grid.Grid;
+import com.extjs.gxt.ui.client.widget.treegrid.TreeGrid;
+import com.extjs.gxt.ui.client.widget.treegrid.WidgetTreeGridCellRenderer;
+import com.google.gwt.user.client.rpc.AsyncCallback;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.AbstractAsyncCallback;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.GenericConstants;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeEntityItemData;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeEntityKindItemData;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeItemData;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeMetaprojectItemData;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget.MetaprojectTreeEntityItemWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget.MetaprojectTreeEntityKindItemWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget.MetaprojectTreeItemWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget.MetaprojectTreeMetaprojectItemWidget;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
+import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithIdentifier;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTree extends TreeGrid<MetaprojectTreeItemData>
+{
+
+    public static final String ID = GenericConstants.ID_PREFIX + "metaproject-tree";
+
+    public static final String COLUMN_ID = "metaproject-tree-column";
+
+    private MetaprojectTreeItemData selectedItem;
+
+    public MetaprojectTree(IViewContext<?> viewContext)
+    {
+        this(viewContext, new MetaprojectTreeLoader(viewContext), new MetaprojectTreeColumns(
+                viewContext));
+    }
+
+    private MetaprojectTree(final IViewContext<?> viewContext, final MetaprojectTreeLoader loader,
+            final MetaprojectTreeColumns columns)
+    {
+        super(new TreeStore<MetaprojectTreeItemData>(loader), columns.getModel());
+
+        setId(ID);
+        setLazyRowRender(0);
+        setBorders(true);
+        setAutoExpandColumn(COLUMN_ID);
+
+        getTreeView().setForceFit(true);
+        getTreeView().setSortingEnabled(false);
+        getTreeView().setBufferEnabled(false);
+
+        getStyle().setNodeCloseIcon(null);
+        getStyle().setNodeOpenIcon(null);
+
+        getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
+        getSelectionModel().addSelectionChangedListener(
+                new SelectionChangedListener<MetaprojectTreeItemData>()
+                    {
+                        @Override
+                        public void selectionChanged(
+                                SelectionChangedEvent<MetaprojectTreeItemData> se)
+                        {
+                            if (selectedItem != null)
+                            {
+                                MetaprojectTreeItemWidget selectedWidget =
+                                        columns.getWidget(selectedItem);
+                                selectedWidget.setSelected(false);
+                            }
+
+                            selectedItem = se.getSelectedItem();
+
+                            if (selectedItem != null)
+                            {
+                                MetaprojectTreeItemWidget selectedWidget =
+                                        columns.getWidget(selectedItem);
+                                selectedWidget.setSelected(true);
+                            }
+                        }
+                    });
+
+        loader.load();
+    }
+
+    private static class MetaprojectTreeProxy extends RpcProxy<List<MetaprojectTreeItemData>>
+    {
+
+        private IViewContext<?> viewContext;
+
+        private Map<Long, MetaprojectAssignmentsCount> countMap;
+
+        public MetaprojectTreeProxy(IViewContext<?> viewContext)
+        {
+            this.viewContext = viewContext;
+        }
+
+        @Override
+        protected void load(Object parentObject,
+                AsyncCallback<List<MetaprojectTreeItemData>> callback)
+        {
+            if (parentObject == null)
+            {
+                loadMetaprojects(callback);
+            } else if (parentObject instanceof MetaprojectTreeMetaprojectItemData)
+            {
+                loadEntityKinds((MetaprojectTreeMetaprojectItemData) parentObject, callback);
+            } else if (parentObject instanceof MetaprojectTreeEntityKindItemData)
+            {
+                loadEntities((MetaprojectTreeEntityKindItemData) parentObject, callback);
+            } else
+            {
+                throw new IllegalArgumentException("Unsupported parent node: " + parentObject);
+            }
+        }
+
+        private void initCountMap(final IDelegatedAction callback)
+        {
+            viewContext.getCommonService().listMetaprojectAssignmentsCounts(
+                    new AbstractAsyncCallback<List<MetaprojectAssignmentsCount>>(viewContext)
+                        {
+                            @Override
+                            protected void process(List<MetaprojectAssignmentsCount> result)
+                            {
+                                Map<Long, MetaprojectAssignmentsCount> map =
+                                        new HashMap<Long, MetaprojectAssignmentsCount>();
+
+                                for (MetaprojectAssignmentsCount resultItem : result)
+                                {
+                                    map.put(resultItem.getMetaproject().getId(), resultItem);
+                                }
+
+                                MetaprojectTreeProxy.this.countMap = map;
+                                callback.execute();
+                            }
+                        });
+        }
+
+        private void loadMetaprojects(final AsyncCallback<List<MetaprojectTreeItemData>> callback)
+        {
+            if (countMap == null)
+            {
+                initCountMap(new IDelegatedAction()
+                    {
+
+                        @Override
+                        public void execute()
+                        {
+                            loadMetaprojects(callback);
+                        }
+                    });
+            } else
+            {
+                List<MetaprojectTreeItemData> items = new ArrayList<MetaprojectTreeItemData>();
+
+                for (MetaprojectAssignmentsCount count : countMap.values())
+                {
+                    items.add(new MetaprojectTreeMetaprojectItemData(count.getMetaproject()));
+                }
+
+                callback.onSuccess(items);
+            }
+        }
+
+        private void loadEntityKinds(final MetaprojectTreeMetaprojectItemData parent,
+                final AsyncCallback<List<MetaprojectTreeItemData>> callback)
+        {
+            if (countMap == null)
+            {
+                initCountMap(new IDelegatedAction()
+                    {
+
+                        @Override
+                        public void execute()
+                        {
+                            loadEntityKinds(parent, callback);
+                        }
+                    });
+            } else
+            {
+                Long metaprojectId = parent.getMetaproject().getId();
+                MetaprojectAssignmentsCount count = countMap.get(metaprojectId);
+                List<MetaprojectTreeItemData> items = new ArrayList<MetaprojectTreeItemData>();
+
+                if (count.getExperimentCount() > 0)
+                {
+                    items.add(new MetaprojectTreeEntityKindItemData(metaprojectId,
+                            EntityKind.EXPERIMENT, count.getExperimentCount()));
+                }
+                if (count.getSampleCount() > 0)
+                {
+                    items.add(new MetaprojectTreeEntityKindItemData(metaprojectId,
+                            EntityKind.SAMPLE, count.getSampleCount()));
+                }
+                if (count.getDataSetCount() > 0)
+                {
+                    items.add(new MetaprojectTreeEntityKindItemData(metaprojectId,
+                            EntityKind.DATA_SET, count.getDataSetCount()));
+                }
+                if (count.getMaterialCount() > 0)
+                {
+                    items.add(new MetaprojectTreeEntityKindItemData(metaprojectId,
+                            EntityKind.MATERIAL, count.getMaterialCount()));
+                }
+
+                callback.onSuccess(items);
+            }
+        }
+
+        private void loadEntities(final MetaprojectTreeEntityKindItemData parent,
+                final AsyncCallback<List<MetaprojectTreeItemData>> callback)
+        {
+            MetaprojectAssignmentsFetchOption fetchOption =
+                    getAssignmentsFetchOption(parent.getEntityKind());
+
+            viewContext.getCommonService().getMetaprojectAssignments(parent.getMetaprojectId(),
+                    new MetaprojectAssignmentsFetchOption[]
+                        { fetchOption },
+                    new AbstractAsyncCallback<MetaprojectAssignments>(viewContext)
+                        {
+                            @Override
+                            protected void process(MetaprojectAssignments result)
+                            {
+                                List<MetaprojectTreeItemData> items =
+                                        new ArrayList<MetaprojectTreeItemData>();
+                                List<? extends IEntityInformationHolderWithIdentifier> entities =
+                                        getAssignmentsEntities(result, parent.getEntityKind());
+
+                                for (IEntityInformationHolderWithIdentifier entity : entities)
+                                {
+                                    items.add(new MetaprojectTreeEntityItemData(parent
+                                            .getMetaprojectId(), entity));
+                                }
+
+                                callback.onSuccess(items);
+                            }
+                        });
+        }
+    }
+
+    private static class MetaprojectTreeLoader extends BaseTreeLoader<MetaprojectTreeItemData>
+    {
+
+        public MetaprojectTreeLoader(final IViewContext<?> viewContext)
+        {
+            super(new MetaprojectTreeProxy(viewContext));
+        }
+
+        @Override
+        public boolean hasChildren(MetaprojectTreeItemData parent)
+        {
+            return parent == null || parent instanceof MetaprojectTreeMetaprojectItemData
+                    || parent instanceof MetaprojectTreeEntityKindItemData;
+        }
+    }
+
+    private static class MetaprojectTreeColumns
+    {
+
+        private ColumnModel columnModel;
+
+        private Map<MetaprojectTreeItemData, MetaprojectTreeItemWidget> widgetMap =
+                new HashMap<MetaprojectTreeItemData, MetaprojectTreeItemWidget>();
+
+        public MetaprojectTreeColumns(final IViewContext<?> viewContext)
+        {
+            ColumnConfig column =
+                    new ColumnConfig(COLUMN_ID,
+                            viewContext.getMessage(Dict.METAPROJECT_TREE_COLUMN_HEADER), 1);
+            column.setMenuDisabled(true);
+            column.setSortable(false);
+            column.setRenderer(new WidgetTreeGridCellRenderer<MetaprojectTreeItemData>()
+                {
+                    @Override
+                    public Widget getWidget(MetaprojectTreeItemData data, String property,
+                            ColumnData config, int rowIndex, int colIndex,
+                            ListStore<MetaprojectTreeItemData> store,
+                            Grid<MetaprojectTreeItemData> grid)
+                    {
+
+                        MetaprojectTreeItemWidget widget;
+
+                        if (data instanceof MetaprojectTreeMetaprojectItemData)
+                        {
+                            widget =
+                                    new MetaprojectTreeMetaprojectItemWidget(viewContext,
+                                            (MetaprojectTreeMetaprojectItemData) data);
+                        } else if (data instanceof MetaprojectTreeEntityKindItemData)
+                        {
+                            widget =
+                                    new MetaprojectTreeEntityKindItemWidget(viewContext,
+                                            (MetaprojectTreeEntityKindItemData) data);
+                        } else if (data instanceof MetaprojectTreeEntityItemData)
+                        {
+                            widget =
+                                    new MetaprojectTreeEntityItemWidget(viewContext,
+                                            (MetaprojectTreeEntityItemData) data);
+                        } else
+                        {
+                            throw new UnsupportedOperationException(
+                                    "Unsupported metaproject tree item");
+                        }
+
+                        widgetMap.put(data, widget);
+                        return widget;
+                    }
+                });
+
+            columnModel = new ColumnModel(Arrays.asList(column));
+        }
+
+        public ColumnModel getModel()
+        {
+            return columnModel;
+        }
+
+        public MetaprojectTreeItemWidget getWidget(MetaprojectTreeItemData data)
+        {
+            return widgetMap.get(data);
+        }
+
+    }
+
+    private static MetaprojectAssignmentsFetchOption getAssignmentsFetchOption(EntityKind entityKind)
+    {
+        if (EntityKind.EXPERIMENT.equals(entityKind))
+        {
+            return MetaprojectAssignmentsFetchOption.EXPERIMENTS;
+        } else if (EntityKind.SAMPLE.equals(entityKind))
+        {
+            return MetaprojectAssignmentsFetchOption.SAMPLES;
+        } else if (EntityKind.DATA_SET.equals(entityKind))
+        {
+            return MetaprojectAssignmentsFetchOption.DATA_SETS;
+        } else if (EntityKind.MATERIAL.equals(entityKind))
+        {
+            return MetaprojectAssignmentsFetchOption.MATERIALS;
+        } else
+        {
+            throw new IllegalArgumentException("Unsupported entity kind: " + entityKind);
+        }
+    }
+
+    private static List<? extends IEntityInformationHolderWithIdentifier> getAssignmentsEntities(
+            MetaprojectAssignments assignments, EntityKind entityKind)
+    {
+        if (EntityKind.EXPERIMENT.equals(entityKind))
+        {
+            return assignments.getExperiments();
+        } else if (EntityKind.SAMPLE.equals(entityKind))
+        {
+            return assignments.getSamples();
+        } else if (EntityKind.DATA_SET.equals(entityKind))
+        {
+            return assignments.getDataSets();
+        } else if (EntityKind.MATERIAL.equals(entityKind))
+        {
+            return assignments.getMaterials();
+        } else
+        {
+            throw new IllegalArgumentException("Unsupported entity kind: " + entityKind);
+        }
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityItemData.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityItemData.java
new file mode 100644
index 00000000000..13bc2aaf56c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityItemData.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithIdentifier;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeEntityItemData extends MetaprojectTreeItemData
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long metaprojectId;
+
+    private IEntityInformationHolderWithIdentifier entity;
+
+    // GWT
+    @SuppressWarnings("unused")
+    private MetaprojectTreeEntityItemData()
+    {
+    }
+
+    public MetaprojectTreeEntityItemData(Long metaprojectId,
+            IEntityInformationHolderWithIdentifier entity)
+    {
+        this.metaprojectId = metaprojectId;
+        this.entity = entity;
+    }
+
+    public Long getMetaprojectId()
+    {
+        return metaprojectId;
+    }
+
+    public IEntityInformationHolderWithIdentifier getEntity()
+    {
+        return entity;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return getMetaprojectId().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+
+        MetaprojectTreeEntityItemData other = (MetaprojectTreeEntityItemData) obj;
+        return getMetaprojectId().equals(other.getMetaprojectId())
+                && getEntity().getEntityKind().equals(other.getEntity().getEntityKind())
+                && getEntity().getId().equals(other.getEntity().getId());
+    }
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityKindItemData.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityKindItemData.java
new file mode 100644
index 00000000000..721649aaa56
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeEntityKindItemData.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeEntityKindItemData extends MetaprojectTreeItemData
+{
+    private static final long serialVersionUID = 1L;
+
+    private Long metaprojectId;
+
+    private EntityKind entityKind;
+
+    private int entityCount;
+
+    // GWT
+    @SuppressWarnings("unused")
+    private MetaprojectTreeEntityKindItemData()
+    {
+    }
+
+    public MetaprojectTreeEntityKindItemData(Long metaprojectId, EntityKind entityKind,
+            int entityCount)
+    {
+        this.metaprojectId = metaprojectId;
+        this.entityKind = entityKind;
+        this.entityCount = entityCount;
+    }
+
+    public Long getMetaprojectId()
+    {
+        return metaprojectId;
+    }
+
+    public EntityKind getEntityKind()
+    {
+        return entityKind;
+    }
+
+    public int getEntityCount()
+    {
+        return entityCount;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return getMetaprojectId().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+
+        MetaprojectTreeEntityKindItemData other = (MetaprojectTreeEntityKindItemData) obj;
+        return getMetaprojectId().equals(other.getMetaprojectId())
+                && getEntityKind().equals(other.getEntityKind());
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeItemData.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeItemData.java
new file mode 100644
index 00000000000..436afe1a55c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeItemData.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.SimplifiedBaseModelData;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeItemData extends SimplifiedBaseModelData
+{
+
+    private static final long serialVersionUID = 1L;
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeMetaprojectItemData.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeMetaprojectItemData.java
new file mode 100644
index 00000000000..33ba933b948
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/model/MetaprojectTreeMetaprojectItemData.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model;
+
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeMetaprojectItemData extends MetaprojectTreeItemData
+{
+    private static final long serialVersionUID = 1L;
+
+    private Metaproject metaproject;
+
+    // GWT
+    @SuppressWarnings("unused")
+    private MetaprojectTreeMetaprojectItemData()
+    {
+    }
+
+    public MetaprojectTreeMetaprojectItemData(Metaproject metaproject)
+    {
+        this.metaproject = metaproject;
+    }
+
+    public Metaproject getMetaproject()
+    {
+        return metaproject;
+    }
+
+    @Override
+    public int hashCode()
+    {
+        return getMetaproject().getId().hashCode();
+    }
+
+    @Override
+    public boolean equals(Object obj)
+    {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+
+        MetaprojectTreeMetaprojectItemData other = (MetaprojectTreeMetaprojectItemData) obj;
+        return getMetaproject().getId().equals(other.getMetaproject().getId());
+    }
+
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityItemWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityItemWidget.java
new file mode 100644
index 00000000000..b212b8c1c89
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityItemWidget.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget;
+
+import com.google.gwt.event.dom.client.ClickEvent;
+import com.google.gwt.event.dom.client.ClickHandler;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.renderer.LinkRenderer;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.LinkExtractor;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.listener.OpenEntityDetailsTabHelper;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeEntityItemData;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.WidgetUtils;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeEntityItemWidget extends MetaprojectTreeItemWidget
+{
+
+    public MetaprojectTreeEntityItemWidget(final IViewContext<?> viewContext,
+            final MetaprojectTreeEntityItemData model)
+    {
+        super(viewContext);
+
+        ClickHandler listener = new ClickHandler()
+            {
+                @Override
+                public void onClick(ClickEvent event)
+                {
+                    OpenEntityDetailsTabHelper.open(viewContext, model.getEntity().getEntityKind(),
+                            model.getEntity().getPermId(),
+                            WidgetUtils.ifSpecialKeyPressed(event.getNativeEvent()));
+                }
+            };
+
+        Widget link =
+                LinkRenderer.getLinkWidget(model.getEntity().getIdentifier(), listener,
+                        LinkExtractor.tryExtract(model.getEntity()));
+
+        initWidget(link);
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityKindItemWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityKindItemWidget.java
new file mode 100644
index 00000000000..c3a393f0700
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeEntityKindItemWidget.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget;
+
+import com.google.gwt.user.client.ui.InlineLabel;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeEntityKindItemData;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeEntityKindItemWidget extends MetaprojectTreeItemWidget
+{
+
+    public MetaprojectTreeEntityKindItemWidget(IViewContext<?> viewContext,
+            MetaprojectTreeEntityKindItemData model)
+    {
+        super(viewContext);
+
+        initWidget(new InlineLabel(model.getEntityKind().name() + " (" + model.getEntityCount()
+                + ")"));
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeItemWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeItemWidget.java
new file mode 100644
index 00000000000..92d11fc9f3c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeItemWidget.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget;
+
+import com.google.gwt.user.client.ui.Composite;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+
+/**
+ * @author pkupczyk
+ */
+public abstract class MetaprojectTreeItemWidget extends Composite
+{
+
+    private IViewContext<?> viewContext;
+
+    private boolean selected;
+
+    public MetaprojectTreeItemWidget(IViewContext<?> viewContext)
+    {
+        this.viewContext = viewContext;
+    }
+
+    public void setSelected(boolean selected)
+    {
+        if (this.selected != selected)
+        {
+            this.selected = selected;
+            onSelectedChange();
+        }
+    }
+
+    public boolean isSelected()
+    {
+        return selected;
+    }
+
+    protected void onSelectedChange()
+    {
+
+    }
+
+    public IViewContext<?> getViewContext()
+    {
+        return viewContext;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeMetaprojectItemWidget.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeMetaprojectItemWidget.java
new file mode 100644
index 00000000000..727523ba91a
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/metaproject/tree/widget/MetaprojectTreeMetaprojectItemWidget.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.widget;
+
+import com.google.gwt.event.dom.client.MouseOutEvent;
+import com.google.gwt.event.dom.client.MouseOutHandler;
+import com.google.gwt.event.dom.client.MouseOverEvent;
+import com.google.gwt.event.dom.client.MouseOverHandler;
+import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.FocusPanel;
+import com.google.gwt.user.client.ui.InlineLabel;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.Dict;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.IViewContext;
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.metaproject.tree.model.MetaprojectTreeMetaprojectItemData;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectTreeMetaprojectItemWidget extends MetaprojectTreeItemWidget
+{
+
+    private Widget link;
+
+    public MetaprojectTreeMetaprojectItemWidget(IViewContext<?> viewContext,
+            MetaprojectTreeMetaprojectItemData model)
+    {
+        super(viewContext);
+
+        // TODO make a real link that opens a metaproject detail view
+        link = new InlineLabel(viewContext.getMessage(Dict.METAPROJECT_TREE_INFO_LINK));
+        link.setVisible(isSelected());
+
+        FlowPanel panel = new FlowPanel();
+        panel.add(new InlineLabel(model.getMetaproject().getName() + " "));
+        panel.add(link);
+
+        FocusPanel focusPanel = new FocusPanel();
+        focusPanel.add(panel);
+        focusPanel.addMouseOverHandler(new MouseOverHandler()
+            {
+                @Override
+                public void onMouseOver(MouseOverEvent event)
+                {
+                    link.setVisible(true);
+                }
+            });
+        focusPanel.addMouseOutHandler(new MouseOutHandler()
+            {
+                @Override
+                public void onMouseOut(MouseOutEvent event)
+                {
+                    link.setVisible(isSelected());
+                }
+            });
+
+        initWidget(focusPanel);
+    }
+
+    @Override
+    protected void onSelectedChange()
+    {
+        link.setVisible(isSelected());
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
index d05cb4e2dee..dea29725155 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/CommonClientService.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
@@ -111,6 +112,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.translator.UserFailure
 import ch.systemsx.cisd.openbis.generic.client.web.server.util.TSVRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.ICommonServer;
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
+import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.id.metaproject.MetaprojectTechIdId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithPermId;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder;
@@ -161,6 +163,9 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
@@ -698,6 +703,30 @@ public final class CommonClientService extends AbstractClientService implements
         return listEntities(metaprojectProvider, criteria);
     }
 
+    @Override
+    public List<MetaprojectAssignmentsCount> listMetaprojectAssignmentsCounts()
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        return commonServer.listMetaprojectAssignmentsCounts(getSessionToken());
+    }
+
+    @Override
+    public MetaprojectAssignments getMetaprojectAssignments(Long metaprojectId,
+            MetaprojectAssignmentsFetchOption[] fetchOptions)
+            throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
+    {
+        EnumSet<MetaprojectAssignmentsFetchOption> fetchOptionsSet =
+                EnumSet.noneOf(MetaprojectAssignmentsFetchOption.class);
+
+        for (MetaprojectAssignmentsFetchOption fetchOption : fetchOptions)
+        {
+            fetchOptionsSet.add(fetchOption);
+        }
+
+        return commonServer.getMetaprojectAssignments(getSessionToken(), new MetaprojectTechIdId(
+                metaprojectId), fetchOptionsSet);
+    }
+
     @Override
     public List<AuthorizationGroup> listAuthorizationGroups()
             throws ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
index 6ecf7dd92d3..c29ceb23f35 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServer.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Date;
 import java.util.EnumMap;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
@@ -207,6 +208,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialTypePropertyType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
@@ -3592,10 +3595,51 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         return MetaprojectTranslator.translate(metaprojectPEs);
     }
 
+    @Override
+    public List<MetaprojectAssignmentsCount> listMetaprojectAssignmentsCounts(String sessionToken)
+    {
+        IMetaprojectDAO metaprojectDAO = getDAOFactory().getMetaprojectDAO();
+
+        List<Metaproject> metaprojects = listMetaprojects(sessionToken);
+        List<MetaprojectAssignmentsCount> counts =
+                new ArrayList<MetaprojectAssignmentsCount>(metaprojects.size());
+
+        for (Metaproject metaproject : metaprojects)
+        {
+            MetaprojectAssignmentsCount count = new MetaprojectAssignmentsCount();
+            count.setMetaproject(metaproject);
+
+            count.setExperimentCount(metaprojectDAO.getMetaprojectAssignmentsCount(
+                    metaproject.getId(),
+                    ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind.EXPERIMENT));
+            count.setSampleCount(metaprojectDAO.getMetaprojectAssignmentsCount(metaproject.getId(),
+                    ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind.SAMPLE));
+            count.setDataSetCount(metaprojectDAO.getMetaprojectAssignmentsCount(
+                    metaproject.getId(),
+                    ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind.DATA_SET));
+            count.setMaterialCount(metaprojectDAO.getMetaprojectAssignmentsCount(
+                    metaproject.getId(),
+                    ch.systemsx.cisd.openbis.generic.shared.dto.properties.EntityKind.MATERIAL));
+
+            counts.add(count);
+        }
+
+        return counts;
+    }
+
     @Override
     @RolesAllowed(RoleWithHierarchy.SPACE_USER)
     public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
             IMetaprojectId metaprojectId)
+    {
+        return getMetaprojectAssignments(sessionToken, metaprojectId,
+                EnumSet.allOf(MetaprojectAssignmentsFetchOption.class));
+    }
+
+    @Override
+    @RolesAllowed(RoleWithHierarchy.SPACE_USER)
+    public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
+            IMetaprojectId metaprojectId, EnumSet<MetaprojectAssignmentsFetchOption> fetchOptions)
     {
         if (metaprojectId == null)
         {
@@ -3625,45 +3669,64 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         List<ExternalData> dataSets = new ArrayList<ExternalData>();
         List<Material> materials = new ArrayList<Material>();
 
-        for (MetaprojectAssignmentPE metaprojectAssignment : metaprojectPE.getAssignments())
+        if (fetchOptions.contains(MetaprojectAssignmentsFetchOption.EXPERIMENTS))
         {
-            if (metaprojectAssignment.getExperiment() != null)
+            for (MetaprojectAssignmentPE metaprojectAssignmentPE : getMetaprojectAssignments(
+                    metaprojectPE, EntityKind.EXPERIMENT))
             {
-                if (authorizationUtils.canAccessExperiment(metaprojectAssignment.getExperiment()))
+                if (authorizationUtils.canAccessExperiment(metaprojectAssignmentPE.getExperiment()))
                 {
                     experiments.add(ExperimentTranslator.translate(
-                            metaprojectAssignment.getExperiment(), baseIndexURL, null,
+                            metaprojectAssignmentPE.getExperiment(), baseIndexURL, null,
                             LoadableFields.PROPERTIES));
                 } else
                 {
                     experiments.add(ExperimentTranslator.translateWithoutRevealingData(
-                            metaprojectAssignment.getExperiment(), null));
+                            metaprojectAssignmentPE.getExperiment(), null));
                 }
-            } else if (metaprojectAssignment.getSample() != null)
+            }
+        }
+
+        if (fetchOptions.contains(MetaprojectAssignmentsFetchOption.SAMPLES))
+        {
+            for (MetaprojectAssignmentPE metaprojectAssignmentPE : getMetaprojectAssignments(
+                    metaprojectPE, EntityKind.SAMPLE))
             {
-                if (authorizationUtils.canAccessSample(metaprojectAssignment.getSample()))
+                if (authorizationUtils.canAccessSample(metaprojectAssignmentPE.getSample()))
                 {
-                    samples.add(SampleTranslator.translate(metaprojectAssignment.getSample(),
+                    samples.add(SampleTranslator.translate(metaprojectAssignmentPE.getSample(),
                             baseIndexURL, null));
                 } else
                 {
                     samples.add(SampleTranslator
-                            .translateWithoutRevealingData(metaprojectAssignment.getSample()));
+                            .translateWithoutRevealingData(metaprojectAssignmentPE.getSample()));
                 }
-            } else if (metaprojectAssignment.getDataSet() != null)
+            }
+        }
+
+        if (fetchOptions.contains(MetaprojectAssignmentsFetchOption.DATA_SETS))
+        {
+            for (MetaprojectAssignmentPE metaprojectAssignmentPE : getMetaprojectAssignments(
+                    metaprojectPE, EntityKind.DATA_SET))
             {
-                if (authorizationUtils.canAccessDataSet(metaprojectAssignment.getDataSet()))
+                if (authorizationUtils.canAccessDataSet(metaprojectAssignmentPE.getDataSet()))
                 {
-                    dataSets.add(DataSetTranslator.translate(metaprojectAssignment.getDataSet(),
+                    dataSets.add(DataSetTranslator.translate(metaprojectAssignmentPE.getDataSet(),
                             baseIndexURL, null));
                 } else
                 {
                     dataSets.add(DataSetTranslator
-                            .translateWithoutRevealingData(metaprojectAssignment.getDataSet()));
+                            .translateWithoutRevealingData(metaprojectAssignmentPE.getDataSet()));
                 }
-            } else if (metaprojectAssignment.getMaterial() != null)
+            }
+        }
+
+        if (fetchOptions.contains(MetaprojectAssignmentsFetchOption.MATERIALS))
+        {
+            for (MetaprojectAssignmentPE metaprojectAssignmentPE : getMetaprojectAssignments(
+                    metaprojectPE, EntityKind.MATERIAL))
             {
-                materials.add(MaterialTranslator.translate(metaprojectAssignment.getMaterial(),
+                materials.add(MaterialTranslator.translate(metaprojectAssignmentPE.getMaterial(),
                         null));
             }
         }
@@ -3813,6 +3876,13 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt
         return MetaprojectTranslator.translate(metaprojectPE);
     }
 
+    private Collection<MetaprojectAssignmentPE> getMetaprojectAssignments(
+            MetaprojectPE metaproject, EntityKind entityKind)
+    {
+        return getDAOFactory().getMetaprojectDAO().listMetaprojectAssignments(metaproject.getId(),
+                DtoConverters.convertEntityKind(entityKind));
+    }
+
     private AuthorizationServiceUtils getAuthorizationService(Session session)
     {
         return new AuthorizationServiceUtils(getDAOFactory(), session.tryGetPerson());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
index 38303d6adb5..9e867816de5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonServerLogger.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.server;
 
 import java.util.Collection;
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -82,6 +83,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
@@ -649,8 +652,7 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
             DataSetRelatedEntities entities, boolean withDetails, String userId)
     {
         logAccess(sessionToken, "list_related_datasets_on_behalf_of_user", "WITH_DETAILS(%s)",
-                "WITH_USER(%s)",
-                withDetails, userId);
+                "WITH_USER(%s)", withDetails, userId);
         return null;
     }
 
@@ -1512,6 +1514,22 @@ final class CommonServerLogger extends AbstractServerLogger implements ICommonSe
         return null;
     }
 
+    @Override
+    public List<MetaprojectAssignmentsCount> listMetaprojectAssignmentsCounts(String sessionToken)
+    {
+        logAccess(sessionToken, "listMetaprojectAssignmentsCounts");
+        return null;
+    }
+
+    @Override
+    public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
+            IMetaprojectId metaprojectId, EnumSet<MetaprojectAssignmentsFetchOption> fetchOptions)
+    {
+        logAccess(sessionToken, "getMetaprojectAssignments",
+                "METAPROJECT_ID(%s) FETCH_OPTIONS(%s)", metaprojectId, fetchOptions);
+        return null;
+    }
+
     @Override
     public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
             IMetaprojectId metaprojectId)
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java
index 7b62a05ea41..1b27fdf01e8 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/IMetaprojectDAO.java
@@ -59,4 +59,17 @@ public interface IMetaprojectDAO extends IGenericDAO<MetaprojectPE>
     public Collection<MetaprojectAssignmentPE> listMetaprojectAssignmentsForEntities(
             PersonPE owner, Collection<? extends IEntityInformationWithPropertiesHolder> entities,
             EntityKind entityKind);
+
+    /**
+     * Lists assignments for the given entity kind and metaproject.
+     */
+    Collection<MetaprojectAssignmentPE> listMetaprojectAssignments(Long metaprojectId,
+            EntityKind entityKind);
+
+    /**
+     * Returns a map with counts of assignments for different entity kinds for the given
+     * metaproject.
+     */
+    public int getMetaprojectAssignmentsCount(Long metaprojectId, EntityKind entityKind);
+
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java
index 8c681123a1d..21675488f37 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/dataaccess/db/MetaprojectDAO.java
@@ -26,6 +26,7 @@ import org.apache.log4j.Logger;
 import org.hibernate.SessionFactory;
 import org.hibernate.criterion.DetachedCriteria;
 import org.hibernate.criterion.Order;
+import org.hibernate.criterion.Projections;
 import org.hibernate.criterion.Restrictions;
 import org.springframework.orm.hibernate3.HibernateTemplate;
 
@@ -163,4 +164,46 @@ public class MetaprojectDAO extends AbstractGenericEntityDAO<MetaprojectPE> impl
 
         return assignments;
     }
+
+    @Override
+    public Collection<MetaprojectAssignmentPE> listMetaprojectAssignments(Long metaprojectId,
+            EntityKind entityKind)
+    {
+        final DetachedCriteria criteria = DetachedCriteria.forClass(MetaprojectAssignmentPE.class);
+        criteria.createAlias("metaproject", "m");
+        criteria.add(Restrictions.eq("m.id", metaprojectId));
+        criteria.add(Restrictions.isNotNull(entityKind.getLabel()));
+        final List<MetaprojectAssignmentPE> assignments =
+                cast(getHibernateTemplate().findByCriteria(criteria));
+
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format("%s(%s, %s): %d metaproject(s) have been found.",
+                    MethodUtils.getCurrentMethod().getName(), metaprojectId, entityKind,
+                    assignments.size()));
+        }
+
+        return assignments;
+    }
+
+    @Override
+    public int getMetaprojectAssignmentsCount(Long metaprojectId, EntityKind entityKind)
+    {
+        final DetachedCriteria criteria = DetachedCriteria.forClass(MetaprojectAssignmentPE.class);
+        criteria.createAlias("metaproject", "m");
+        criteria.add(Restrictions.eq("m.id", metaprojectId));
+        criteria.add(Restrictions.isNotNull(entityKind.getLabel()));
+        criteria.setProjection(Projections.rowCount());
+
+        Number count = (Number) getHibernateTemplate().findByCriteria(criteria).get(0);
+        
+        if (operationLog.isDebugEnabled())
+        {
+            operationLog.debug(String.format("%s(%s, %s): %d metaproject assignments have been found.",
+                    MethodUtils.getCurrentMethod().getName(), metaprojectId, entityKind,
+                    count));
+        }
+        
+        return count.intValue();
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
index 101aee494af..27456fc4d58 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/ICommonServer.java
@@ -18,6 +18,7 @@ package ch.systemsx.cisd.openbis.generic.shared;
 
 import java.util.Collection;
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -80,6 +81,8 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Metaproject;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignments;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsCount;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MetaprojectAssignmentsFetchOption;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAttachment;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewAuthorizationGroup;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewColumnOrFilter;
@@ -1374,12 +1377,25 @@ public interface ICommonServer extends IServer
     @Transactional(readOnly = true)
     public List<Metaproject> listMetaprojects(String sessionToken);
 
+    /**
+     * Lists all metaproject assignments counts for given user.
+     */
+    @Transactional(readOnly = true)
+    public List<MetaprojectAssignmentsCount> listMetaprojectAssignmentsCounts(String sessionToken);
+
     /**
      * Returns object containing all entities assigned to given metaproject.
      */
     @Transactional(readOnly = true)
     public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
-            IMetaprojectId metaproject);
+            IMetaprojectId metaprojectId);
+
+    /**
+     * Returns object containing chosen entities assigned to given metaproject.
+     */
+    @Transactional(readOnly = true)
+    public MetaprojectAssignments getMetaprojectAssignments(String sessionToken,
+            IMetaprojectId metaprojectId, EnumSet<MetaprojectAssignmentsFetchOption> fetchOptions);
 
     /**
      * Adds specified entities to given metaproject.
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsCount.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsCount.java
new file mode 100644
index 00000000000..82090d8320c
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsCount.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+import java.io.Serializable;
+
+/**
+ * @author pkupczyk
+ */
+public class MetaprojectAssignmentsCount implements Serializable
+{
+
+    private static final long serialVersionUID = ServiceVersionHolder.VERSION;
+
+    private Metaproject metaproject;
+
+    private int experimentCount;
+
+    private int sampleCount;
+
+    private int dataSetCount;
+
+    private int materialCount;
+
+    public Metaproject getMetaproject()
+    {
+        return metaproject;
+    }
+
+    public void setMetaproject(Metaproject metaproject)
+    {
+        this.metaproject = metaproject;
+    }
+
+    public int getExperimentCount()
+    {
+        return experimentCount;
+    }
+
+    public void setExperimentCount(int experimentCount)
+    {
+        this.experimentCount = experimentCount;
+    }
+
+    public int getSampleCount()
+    {
+        return sampleCount;
+    }
+
+    public void setSampleCount(int sampleCount)
+    {
+        this.sampleCount = sampleCount;
+    }
+
+    public int getDataSetCount()
+    {
+        return dataSetCount;
+    }
+
+    public void setDataSetCount(int dataSetCount)
+    {
+        this.dataSetCount = dataSetCount;
+    }
+
+    public int getMaterialCount()
+    {
+        return materialCount;
+    }
+
+    public void setMaterialCount(int materialCount)
+    {
+        this.materialCount = materialCount;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsFetchOption.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsFetchOption.java
new file mode 100644
index 00000000000..6c08407e831
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/MetaprojectAssignmentsFetchOption.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2012 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.openbis.generic.shared.basic.dto;
+
+/**
+ * @author pkupczyk
+ */
+public enum MetaprojectAssignmentsFetchOption implements FetchOption
+{
+
+    EXPERIMENTS, SAMPLES, DATA_SETS, MATERIALS;
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
index 91889a4d153..eb3cd2e0622 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/common-dictionary.js
@@ -474,6 +474,8 @@ var common = {
   PROJECT_MENU_BROWSE: "Projects",
   PROJECT_MENU_NEW: "Project",
   
+  METAPROJECT_MENU_BROWSE: "Metaprojects",
+  
   menu_property_types: "Metadata",
   PROPERTY_TYPES_MENU_BROWSE_PROPERTY_TYPES: "Browse Property Types",
   PROPERTY_TYPES_MENU_BROWSE_ASSIGNMENTS: "Browse Assignments",
@@ -605,6 +607,7 @@ var common = {
   HELP__TABLE_SETTINGS__CUSTOM_FILTER__EDIT: "Add or Edit Custom Filter",
   HELP__EXPORT_DATA__ACTION: "Data Exporting",
   HELP__PERFORM_COMPUTATION__ACTION: "Performing Computations on Data Sets",
+  HELP__METAPROJECT__BROWSE: "Metaproject Browser",
     
   //
   // User Settings Dialog
@@ -723,6 +726,20 @@ var common = {
  //
  project_browser: "Project Browser",
 
+ //
+ // Metaproject Tree
+ //
+ 
+ metaproject_tree_column_header: "Metaproject / Entity Kind / Entity",
+ metaproject_tree_info_link: "(info)",
+ 
+ //
+ // Metaproject Browser
+ //
+ metaproject_browser: "Metaproject Browser",
+ metaproject_browser_tree_title: "Metaprojects",
+ metaproject_browser_tree_tooltip: "Click on a row with an entity type (i.e. Experiments, Samples, Data Sets, Materials) to see entities of that type that belong to the given metaproject.",
+
  //
  // Project Registration
  //
-- 
GitLab