From ff68e60f86af15b28066655af00faec7c31c9f2e Mon Sep 17 00:00:00 2001
From: gpawel <gpawel>
Date: Wed, 11 Jul 2012 08:12:15 +0000
Subject: [PATCH] SP-198 BIS-120: Table editing behavior

SVN: 26067
---
 .../client/application/GenericViewModel.java  |   6 +
 .../application/model/BaseEntityModel.java    |  25 +++
 .../application/renderer/PersonRenderer.java  |  15 +-
 .../client/application/ui/TypedTableGrid.java |  15 +-
 .../ui/TypedTableGridColumnDefinitionUI.java  |   6 +
 .../framework/IColumnDefinitionUI.java        |   5 +
 .../specific/GridCustomColumnDefinition.java  |   6 +
 .../ui/data/AbstractExternalDataGrid.java     |   3 +-
 .../ui/experiment/ExperimentBrowserGrid.java  |   3 +-
 .../application/ui/grid/ExtendedGridView.java | 167 ++++++++++++++++++
 .../application/ui/project/ProjectGrid.java   |   3 +-
 .../ui/sample/SampleBrowserGrid.java          |   3 +-
 .../web/client/dto/CommonGridColumnIDs.java   |  29 +++
 .../dto/ExperimentBrowserGridColumnIDs.java   |   4 -
 .../client/dto/ExternalDataGridColumnIDs.java |   4 -
 .../web/client/dto/ProjectGridColumnIDs.java  |   4 -
 .../web/client/dto/SampleGridColumnIDs.java   |   4 -
 .../generic/client/web/client/dto/User.java   |  17 +-
 .../web/server/AbstractClientService.java     |   1 +
 .../AbstractExternalDataProvider.java         |   4 +-
 .../resultset/AbstractMaterialProvider.java   |   2 +-
 .../server/resultset/ExperimentProvider.java  |   4 +-
 .../server/resultset/ProjectsProvider.java    |   4 +-
 .../web/server/resultset/SampleProvider.java  |   4 +-
 .../generic/server/AbstractServer.java        |   2 +
 .../bo/common/BaseEntityPropertyRecord.java   |   6 +-
 .../bo/common/EntityPropertiesEnricher.java   |   2 +
 .../datasetlister/IDatasetListingQuery.java   |   3 +-
 .../materiallister/IMaterialListingQuery.java |   3 +-
 .../bo/samplelister/ISampleListingQuery.java  |   3 +-
 .../basic/dto/AbstractEntityProperty.java     |  15 +-
 .../shared/basic/dto/IEntityProperty.java     |   2 +
 .../basic/dto/ManagedEntityProperty.java      |  10 +-
 .../basic/dto/TableModelColumnHeader.java     |  12 ++
 .../generic/shared/dto/SessionContextDTO.java |  12 ++
 .../translator/PropertyTranslatorUtils.java   |   1 +
 .../openbis/generic/shared/util/IColumn.java  |   5 +
 .../shared/util/TypedTableModelBuilder.java   |  16 ++
 .../cisd/openbis/public/css/openbis.css       |  13 ++
 .../cisd/openbis/public/images/outdated.gif   | Bin 0 -> 832 bytes
 40 files changed, 396 insertions(+), 47 deletions(-)
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/CommonGridColumnIDs.java
 create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/public/images/outdated.gif

diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/GenericViewModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/GenericViewModel.java
index f14dd347b31..b24e5b9b366 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/GenericViewModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/GenericViewModel.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ApplicationInfo;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SessionContext;
 import ch.systemsx.cisd.openbis.generic.shared.basic.ViewMode;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 
 /**
  * The view model.
@@ -89,4 +90,9 @@ public class GenericViewModel
     {
         return anonymousAllowed;
     }
+
+    public Person getLoggedInPerson()
+    {
+        return sessionContext.getUser().getUserPersonObject();
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
index 345e33857da..4a200731731 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/model/BaseEntityModel.java
@@ -16,8 +16,10 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.client.application.model;
 
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns.framework.IColumnDefinitionUI;
 import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
@@ -35,6 +37,10 @@ public class BaseEntityModel<T> extends SimplifiedBaseModelData
 {
     private static final long serialVersionUID = 1L;
 
+    private boolean outdated = false;
+
+    private final Set<String> outdatable = new HashSet<String>();
+
     /** NOTE: it's assumed that columnDefinitions do not contain custom columns */
     public BaseEntityModel(final GridRowModel<T> entity,
             List<? extends IColumnDefinition<T>> columnDefinitions)
@@ -49,6 +55,10 @@ public class BaseEntityModel<T> extends SimplifiedBaseModelData
             {
                 set(ModelDataPropertyNames.link(column.getIdentifier()),
                         ((IColumnDefinitionUI<T>) column).tryGetLink(entity.getOriginalObject()));
+                if (((IColumnDefinitionUI<?>) column).isDynamicProperty())
+                {
+                    outdatable.add(column.getIdentifier());
+                }
             }
         }
         addCustomColumns(entity);
@@ -59,6 +69,7 @@ public class BaseEntityModel<T> extends SimplifiedBaseModelData
         for (Entry<String, PrimitiveValue> entry : model.getCalculatedColumnValues().entrySet())
         {
             set(entry.getKey(), entry.getValue());
+            outdatable.add(entry.getKey());
         }
     }
 
@@ -72,4 +83,18 @@ public class BaseEntityModel<T> extends SimplifiedBaseModelData
         return get(ModelDataPropertyNames.link(columnId));
     }
 
+    public boolean isOutdated()
+    {
+        return outdated;
+    }
+
+    public void setOutdated(boolean outdated)
+    {
+        this.outdated = outdated;
+    }
+
+    public boolean isOutdatable(String columnName)
+    {
+        return outdatable.contains(columnName);
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/PersonRenderer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/PersonRenderer.java
index f64962e97c9..914c3a37cc0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/PersonRenderer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/renderer/PersonRenderer.java
@@ -82,10 +82,17 @@ public final class PersonRenderer
                             ColumnData config, int rowIndex, int colIndex,
                             ListStore<BaseEntityModel<?>> store, Grid<BaseEntityModel<?>> grid)
                     {
-                        Person registrator =
-                                ((TableModelRowWithObject<IRegistratorAndModifierHolder>) model
-                                        .getBaseObject()).getObjectOrNull().getModifier();
-                        return PersonRenderer.createPersonAnchor(registrator);
+                        Person modifier = null;
+                        if (model.get(property) != null && model.get(property) instanceof Person)
+                        {
+                            modifier = model.get(property);
+                        } else
+                        {
+                            modifier =
+                                    ((TableModelRowWithObject<IRegistratorAndModifierHolder>) model
+                                            .getBaseObject()).getObjectOrNull().getModifier();
+                        }
+                        return PersonRenderer.createPersonAnchor(modifier);
                     }
                 };
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
index a9edbc747c3..c4ea1a2fdc7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGrid.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui;
 import java.io.Serializable;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
@@ -132,6 +133,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDele
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.WindowUtils;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.lang.StringEscapeUtils;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.Constants;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.EntityPropertyUpdatesResult;
@@ -149,12 +151,14 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.GridRowModel;
 import ch.systemsx.cisd.openbis.generic.shared.basic.IColumnDefinition;
 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.SimpleDateRenderer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.URLMethodWithParameters;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BasicEntityDescription;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.BasicEntityType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ColumnSetting;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataTypeCode;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DatabaseModificationKind;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DateTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityKind;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.EntityTableCell;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.IEntityPropertiesHolder;
@@ -2398,7 +2402,7 @@ public abstract class TypedTableGrid<T extends Serializable> extends LayoutConta
                         }
                         if (isApplyModificationsComplete())
                         {
-                            onApplyModificationsComplete();
+                            onApplyModificationsComplete(model);
                         }
                     }
 
@@ -2409,7 +2413,7 @@ public abstract class TypedTableGrid<T extends Serializable> extends LayoutConta
                         handleError(caught.getMessage());
                         if (isApplyModificationsComplete())
                         {
-                            onApplyModificationsComplete();
+                            onApplyModificationsComplete(model);
                         }
                     }
 
@@ -2427,7 +2431,7 @@ public abstract class TypedTableGrid<T extends Serializable> extends LayoutConta
             return finishedModifications == modificationsByModel.size();
         }
 
-        private void onApplyModificationsComplete()
+        private void onApplyModificationsComplete(BaseEntityModel<TableModelRowWithObject<T>> model)
         {
             if (failedModifications.size() > 0)
             {
@@ -2440,6 +2444,10 @@ public abstract class TypedTableGrid<T extends Serializable> extends LayoutConta
             } else
             {
                 GWTUtils.displayInfo("All modifications successfully applied.");
+                model.setOutdated(true);
+                model.set(CommonGridColumnIDs.MODIFIER, viewContext.getModel().getLoggedInPerson());
+                model.set(CommonGridColumnIDs.MODIFICATION_DATE, SimpleDateRenderer
+                        .renderDate((new DateTableCell(new Date())).getDateTime()));
                 grid.getStore().commitChanges(); // no need to refresh - everything should be valid
             }
             clearModifications();
@@ -2501,7 +2509,6 @@ public abstract class TypedTableGrid<T extends Serializable> extends LayoutConta
                     }
                 }));
         }
-
     }
 
     /**
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGridColumnDefinitionUI.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGridColumnDefinitionUI.java
index 66e82c3f779..f8fd6027725 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGridColumnDefinitionUI.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/TypedTableGridColumnDefinitionUI.java
@@ -79,6 +79,12 @@ public class TypedTableGridColumnDefinitionUI<T extends Serializable> extends
         return header.isEditable();
     }
 
+    @Override
+    public boolean isDynamicProperty()
+    {
+        return header.isDynamicProperty();
+    }
+
     public boolean isLink()
     {
         return false;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java
index e9d5a12e208..c7363fc9166 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/framework/IColumnDefinitionUI.java
@@ -37,4 +37,9 @@ public interface IColumnDefinitionUI<T> extends IColumnDefinition<T>
     Vocabulary tryGetVocabulary();
 
     String tryGetLink(T entity);
+
+    /**
+     * Returns <code>true</code> if the column cell is a dynamic property
+     */
+    boolean isDynamicProperty();
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
index b72a7ea05fc..51fbc2fdbee 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/columns/specific/GridCustomColumnDefinition.java
@@ -74,6 +74,12 @@ public class GridCustomColumnDefinition<T> implements IColumnDefinitionUI<T>
         return false;
     }
 
+    @Override
+    public boolean isDynamicProperty()
+    {
+        return false;
+    }
+
     public boolean isLink()
     {
         return false;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java
index 3fd598a4a79..ee03c2f7d1f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/data/AbstractExternalDataGrid.java
@@ -48,6 +48,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.en
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.listener.OpenEntityDetailsTabHelper;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedActionWithResult;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.TextToolItem;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DisplayedOrSelectedDatasetCriteria;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -287,7 +288,7 @@ public abstract class AbstractExternalDataGrid extends AbstractEntityGrid<Extern
                 super.createColumnsDefinition();
         schema.setGridCellRendererFor(ExternalDataGridColumnIDs.REGISTRATOR,
                 PersonRenderer.REGISTRATOR_RENDERER);
-        schema.setGridCellRendererFor(ExternalDataGridColumnIDs.MODIFIER,
+        schema.setGridCellRendererFor(CommonGridColumnIDs.MODIFIER,
                 PersonRenderer.MODIFIER_RENDERER);
         schema.setGridCellRendererFor(ExternalDataGridColumnIDs.SHOW_DETAILS_LINK,
                 createShowDetailsLinkCellRenderer());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
index dd22513cf05..187f3451d0e 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/experiment/ExperimentBrowserGrid.java
@@ -55,6 +55,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDele
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedActionWithResult;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IMessageProvider;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.TextToolItem;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListExperimentsCriteria;
@@ -336,7 +337,7 @@ public class ExperimentBrowserGrid extends AbstractEntityGrid<Experiment>
                 super.createColumnsDefinition();
         schema.setGridCellRendererFor(ExperimentBrowserGridColumnIDs.REGISTRATOR,
                 PersonRenderer.REGISTRATOR_RENDERER);
-        schema.setGridCellRendererFor(ExperimentBrowserGridColumnIDs.MODIFIER,
+        schema.setGridCellRendererFor(CommonGridColumnIDs.MODIFIER,
                 PersonRenderer.MODIFIER_RENDERER);
         schema.setGridCellRendererFor(ExperimentBrowserGridColumnIDs.SHOW_DETAILS_LINK,
                 createShowDetailsLinkCellRenderer());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ExtendedGridView.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ExtendedGridView.java
index 3588cbc6fa4..3b097fe1141 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ExtendedGridView.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/grid/ExtendedGridView.java
@@ -3,16 +3,27 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid;
 import java.util.ArrayList;
 import java.util.List;
 
+import com.extjs.gxt.ui.client.GXT;
+import com.extjs.gxt.ui.client.core.XDOM;
 import com.extjs.gxt.ui.client.data.ModelData;
 import com.extjs.gxt.ui.client.event.ComponentEvent;
 import com.extjs.gxt.ui.client.event.GridEvent;
+import com.extjs.gxt.ui.client.store.Record;
+import com.extjs.gxt.ui.client.widget.grid.CheckBoxSelectionModel;
+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.ColumnHeader;
 import com.extjs.gxt.ui.client.widget.grid.Grid;
 import com.extjs.gxt.ui.client.widget.grid.GridView;
+import com.extjs.gxt.ui.client.widget.grid.RowExpander;
+import com.extjs.gxt.ui.client.widget.grid.RowNumberer;
 import com.extjs.gxt.ui.client.widget.menu.Menu;
 import com.google.gwt.dom.client.Node;
 import com.google.gwt.dom.client.NodeList;
 import com.google.gwt.user.client.Element;
+import com.google.gwt.user.client.ui.Widget;
+
+import ch.systemsx.cisd.openbis.generic.client.web.client.application.model.BaseEntityModel;
 
 /**
  * {@link GridView} with {@link ColumnHeader} allowing to define additional behavior for header
@@ -152,4 +163,160 @@ public class ExtendedGridView extends GridView
         return headerCellIndex;
     }
 
+    @Override
+    // WORKAROUND extended rendering of the cells to include information about potentially outdated
+    // values (see SP-198). Basically the method was copied from super class ant only part
+    // responsible for rendering outdated cells was added.
+    protected String doRender(List<ColumnData> cs, List<ModelData> rows, int startRow,
+            int colCount, boolean stripe)
+    {
+        int last = colCount - 1;
+        String tstyle = "width:" + getTotalWidth() + "px;";
+
+        StringBuilder buf = new StringBuilder();
+
+        for (int j = 0; j < rows.size(); j++)
+        {
+            @SuppressWarnings("cast")
+            ModelData model = (ModelData) rows.get(j);
+
+            model = prepareData(model);
+
+            Record r = ds.hasRecord(model) ? ds.getRecord(model) : null;
+
+            int rowBodyColSpanCount = colCount;
+            if (enableRowBody)
+            {
+                if (grid.getSelectionModel() instanceof CheckBoxSelectionModel<?>)
+                {
+                    CheckBoxSelectionModel<?> sm =
+                            (CheckBoxSelectionModel<?>) grid.getSelectionModel();
+                    if (cm.getColumnById(sm.getColumn().getId()) != null)
+                    {
+                        rowBodyColSpanCount--;
+                    }
+                }
+                for (ColumnConfig c : cm.getColumns())
+                {
+                    if (c instanceof RowExpander || c instanceof RowNumberer)
+                    {
+                        rowBodyColSpanCount--;
+                    }
+                }
+            }
+            int rowIndex = (j + startRow);
+
+            if (GXT.isAriaEnabled())
+            {
+                buf.append("<div role=\"row\" aria-level=\"2\" class=\"x-grid3-row ");
+            } else
+            {
+                buf.append("<div class=\"x-grid3-row ");
+            }
+
+            if (stripe && ((rowIndex + 1) % 2 == 0))
+            {
+                buf.append(" x-grid3-row-alt");
+            }
+            if (!selectable)
+            {
+                buf.append(" x-unselectable-single");
+            }
+
+            if (super.isShowDirtyCells() && r != null && r.isDirty())
+            {
+                buf.append(" x-grid3-dirty-row");
+            }
+            if (viewConfig != null)
+            {
+                buf.append(" ");
+                buf.append(viewConfig.getRowStyle(model, rowIndex, ds));
+            }
+            buf.append("\" style=\"");
+            buf.append(tstyle);
+            buf.append("\" id=\"");
+            buf.append(grid.getId());
+            buf.append("_");
+            buf.append(ds.getKeyProvider() != null ? ds.getKeyProvider().getKey(model) : XDOM
+                    .getUniqueId());
+            buf.append("\" unselectable=\"");
+            buf.append(selectable ? "off" : "on");
+            buf.append("\"><table class=x-grid3-row-table role=presentation border=0 cellspacing=0 cellpadding=0 style=\"");
+
+            buf.append(tstyle);
+            buf.append("\"><tbody role=presentation><tr role=presentation>");
+            widgetList.add(rowIndex, new ArrayList<Widget>());
+            for (int i = 0; i < colCount; i++)
+            {
+                ColumnData c = cs.get(i);
+                c.css = c.css == null ? "" : c.css;
+                String rv = getRenderedValue(c, rowIndex, i, model, c.name);
+                String role = "gridcell";
+                if (GXT.isAriaEnabled())
+                {
+                    ColumnConfig cc = cm.getColumn(i);
+                    if (cc.isRowHeader())
+                    {
+                        role = "rowheader";
+                    }
+                }
+
+                String attr = c.cellAttr != null ? c.cellAttr : "";
+                String cellAttr = c.cellAttr != null ? c.cellAttr : "";
+
+                buf.append("<td id=\"" + XDOM.getUniqueId() + "\" role=\"" + role
+                        + "\" class=\"x-grid3-col x-grid3-cell x-grid3-td-");
+                buf.append(c.id);
+                buf.append(" ");
+                buf.append(i == 0 ? "x-grid-cell-first " : (i == last ? "x-grid3-cell-last " : ""));
+                if (c.css != null)
+                {
+                    buf.append(c.css);
+                }
+                if (super.isShowInvalidCells() && r != null && !r.isValid(c.name))
+                {
+                    buf.append(" x-grid3-invalid-cell");
+                }
+                if (super.isShowDirtyCells() && r != null && r.getChanges().containsKey(c.name))
+                {
+                    buf.append(" x-grid3-dirty-cell");
+                } else
+                { // rendiring of the outdated cells
+                    if (model instanceof BaseEntityModel<?>)
+                    {
+                        BaseEntityModel<?> baseEntityModel = (BaseEntityModel<?>) model;
+                        if (baseEntityModel.isOutdated() && baseEntityModel.isOutdatable(c.name))
+                        {
+                            buf.append(" cisd-grid-outdated-cell");
+                        }
+                    } // and of the rendering of the outdated cells
+                }
+
+                buf.append("\" style=\"");
+                buf.append(c.style);
+                buf.append("\" ");
+                buf.append(cellAttr);
+                buf.append("><div unselectable=\"");
+                buf.append(selectable ? "off" : "on");
+                buf.append("\" class=\"x-grid3-cell-inner x-grid3-col-");
+                buf.append(c.id);
+                buf.append("\" ");
+                buf.append(attr);
+                buf.append(">");
+                buf.append(rv);
+                buf.append("</div></td>");
+            }
+
+            buf.append("</tr>");
+            if (enableRowBody)
+            {
+                buf.append("<tr class=x-grid3-row-body-tr style=\"\"><td colspan=");
+                buf.append(rowBodyColSpanCount);
+                buf.append(" class=x-grid3-body-cell><div class=x-grid3-row-body>${body}</div></td></tr>");
+            }
+            buf.append("</tbody></table></div>");
+        }
+
+        return buf.toString();
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java
index bef71486361..527ae07b3bc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/project/ProjectGrid.java
@@ -50,6 +50,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.columns
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.ColumnDefsAndConfigs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IBrowserGridActionInvoker;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.grid.IDisposableComponent;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.TableExportCriteria;
@@ -179,7 +180,7 @@ public class ProjectGrid extends TypedTableGrid<Project>
                 createMultilineStringCellRenderer());
         schema.setGridCellRendererFor(ProjectGridColumnIDs.REGISTRATOR,
                 PersonRenderer.REGISTRATOR_RENDERER);
-        schema.setGridCellRendererFor(ProjectGridColumnIDs.MODIFIER,
+        schema.setGridCellRendererFor(CommonGridColumnIDs.MODIFIER,
                 PersonRenderer.MODIFIER_RENDERER);
         return schema;
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
index f7ae5b7b2a3..e39848020f2 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/ui/sample/SampleBrowserGrid.java
@@ -57,6 +57,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.widget.
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedAction;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDelegatedActionWithResult;
 import ch.systemsx.cisd.openbis.generic.client.web.client.application.util.IDirectlyConnectedController;
+import ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.DefaultResultSetConfig;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListEntityDisplayCriteriaKind;
 import ch.systemsx.cisd.openbis.generic.client.web.client.dto.ListSampleDisplayCriteria;
@@ -433,7 +434,7 @@ public class SampleBrowserGrid extends AbstractEntityGrid<Sample>
                 super.createColumnsDefinition();
         definitions.setGridCellRendererFor(SampleGridColumnIDs.REGISTRATOR,
                 PersonRenderer.REGISTRATOR_RENDERER);
-        definitions.setGridCellRendererFor(SampleGridColumnIDs.MODIFIER,
+        definitions.setGridCellRendererFor(CommonGridColumnIDs.MODIFIER,
                 PersonRenderer.MODIFIER_RENDERER);
         definitions.setGridCellRendererFor(SampleGridColumnIDs.SHOW_DETAILS_LINK_COLUMN_NAME,
                 createShowDetailsLinkCellRenderer());
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/CommonGridColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/CommonGridColumnIDs.java
new file mode 100644
index 00000000000..2df7936d460
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/CommonGridColumnIDs.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.dto;
+
+/**
+ * IDs of static columns common to many grids
+ * 
+ * @author Pawel Glyzewski
+ */
+public class CommonGridColumnIDs
+{
+    public static final String MODIFIER = "MODIFIER";
+
+    public static final String MODIFICATION_DATE = "MODIFICATION_DATE";
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExperimentBrowserGridColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExperimentBrowserGridColumnIDs.java
index 3bf00449745..74e4bdba1aa 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExperimentBrowserGridColumnIDs.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExperimentBrowserGridColumnIDs.java
@@ -37,12 +37,8 @@ public class ExperimentBrowserGridColumnIDs
 
     public static final String REGISTRATOR = "REGISTRATOR";
 
-    public static final String MODIFIER = "MODIFIER";
-
     public static final String REGISTRATION_DATE = "REGISTRATION_DATE";
 
-    public static final String MODIFICATION_DATE = "MODIFICATION_DATE";
-
     public static final String IS_DELETED = "IS_DELETED";
 
     public static final String PERM_ID = "PERM_ID";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExternalDataGridColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExternalDataGridColumnIDs.java
index 5206beb6940..bc930ba972c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExternalDataGridColumnIDs.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ExternalDataGridColumnIDs.java
@@ -54,12 +54,8 @@ public class ExternalDataGridColumnIDs
 
     public static final String REGISTRATOR = "REGISTRATOR";
 
-    public static final String MODIFIER = "MODIFIER";
-
     public static final String REGISTRATION_DATE = "REGISTRATION_DATE";
 
-    public static final String MODIFICATION_DATE = "MODIFICATION_DATE";
-
     public static final String IS_DELETED = "IS_DELETED";
 
     public static final String SOURCE_TYPE = "SOURCE_TYPE";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ProjectGridColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ProjectGridColumnIDs.java
index 78036df077d..c7da1f69fbc 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ProjectGridColumnIDs.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/ProjectGridColumnIDs.java
@@ -34,8 +34,4 @@ public class ProjectGridColumnIDs
     public static final String REGISTRATOR = "REGISTRATOR";
 
     public static final String REGISTRATION_DATE = "REGISTRATION_DATE";
-
-    public static final String MODIFIER = "MODIFIER";
-
-    public static final String MODIFICATION_DATE = "MODIFICATION_DATE";
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SampleGridColumnIDs.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SampleGridColumnIDs.java
index 20c6ce6aa0d..83a763fa5a6 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SampleGridColumnIDs.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/SampleGridColumnIDs.java
@@ -33,12 +33,8 @@ public class SampleGridColumnIDs
 
     public static final String REGISTRATOR = "REGISTRATOR";
 
-    public static final String MODIFIER = "MODIFIER";
-
     public static final String REGISTRATION_DATE = "REGISTRATION_DATE";
 
-    public static final String MODIFICATION_DATE = "MODIFICATION_DATE";
-
     public static final String SAMPLE_TYPE = "SAMPLE_TYPE";
 
     public static final String DATABASE_INSTANCE = "DATABASE_INSTANCE";
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/User.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/User.java
index 392d5d2e3d7..7110c697c5d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/User.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/client/dto/User.java
@@ -18,6 +18,8 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.dto;
 
 import com.google.gwt.user.client.rpc.IsSerializable;
 
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
+
 /**
  * User information to be shown in Web client.
  * 
@@ -31,15 +33,19 @@ public final class User implements IsSerializable
 
     private String userEmail;
 
+    private Person userPersonObject;
+
     public User()
     {
     }
 
-    public User(String userName, String homeGroupCodeOrNull, String userEmail)
+    public User(String userName, String homeGroupCodeOrNull, String userEmail,
+            Person userPersonObject)
     {
         this.userName = userName;
         this.homeGroupCode = homeGroupCodeOrNull;
         this.userEmail = userEmail;
+        this.userPersonObject = userPersonObject;
     }
 
     /** can be null */
@@ -73,4 +79,13 @@ public final class User implements IsSerializable
         return userEmail;
     }
 
+    public Person getUserPersonObject()
+    {
+        return userPersonObject;
+    }
+
+    public void setUserPersonObject(Person userPersonObject)
+    {
+        this.userPersonObject = userPersonObject;
+    }
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java
index a4425988bf0..e8b1e22a662 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/AbstractClientService.java
@@ -312,6 +312,7 @@ public abstract class AbstractClientService implements IClientService,
         user.setUserName(session.getUserName());
         user.setHomeGroupCode(session.tryGetHomeGroupCode());
         user.setUserEmail(session.getUserEmail());
+        user.setUserPersonObject(session.getUserPersonObject());
         sessionContext.setUser(user);
         sessionContext.setAnonymous(session.isAnonymous());
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractExternalDataProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractExternalDataProvider.java
index 7b102894603..d2953c0945d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractExternalDataProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractExternalDataProvider.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFICATION_DATE;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.ARCHIVING_STATUS;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.CODE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.CONTAINER_DATASET;
@@ -33,8 +35,6 @@ import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDat
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.IS_COMPLETE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.IS_DELETED;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.LOCATION;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.MODIFICATION_DATE;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.ORDER_IN_CONTAINER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.PARENT_DATASETS;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.PERM_ID;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractMaterialProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractMaterialProvider.java
index c8a227c7c79..ee38b64ac7c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractMaterialProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/AbstractMaterialProvider.java
@@ -16,7 +16,7 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.MODIFICATION_DATE;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFICATION_DATE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.REGISTRATION_DATE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExternalDataGridColumnIDs.REGISTRATOR;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.MaterialGridColumnIDs.CODE;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java
index 0ef7b239776..d6188e11231 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ExperimentProvider.java
@@ -16,13 +16,13 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFICATION_DATE;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.CODE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.DATABASE_INSTANCE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.EXPERIMENT_IDENTIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.EXPERIMENT_TYPE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.IS_DELETED;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.MODIFICATION_DATE;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.PERM_ID;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.PROJECT;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ExperimentBrowserGridColumnIDs.REGISTRATION_DATE;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ProjectsProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ProjectsProvider.java
index 2ca04ca35ff..62d128baaec 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ProjectsProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/ProjectsProvider.java
@@ -16,10 +16,10 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFICATION_DATE;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.CODE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.DESCRIPTION;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.MODIFICATION_DATE;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.REGISTRATION_DATE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.REGISTRATOR;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.ProjectGridColumnIDs.SPACE;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java
index c573cd0e5e7..83db1227003 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/resultset/SampleProvider.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.openbis.generic.client.web.server.resultset;
 
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFICATION_DATE;
+import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.CommonGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.CODE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.CONTAINER_SAMPLE;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.DATABASE_INSTANCE;
@@ -23,8 +25,6 @@ import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridC
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.EXPERIMENT_IDENTIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.IS_DELETED;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.IS_INSTANCE_SAMPLE;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.MODIFICATION_DATE;
-import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.MODIFIER;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.PARENTS;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.PERM_ID;
 import static ch.systemsx.cisd.openbis.generic.client.web.client.dto.SampleGridColumnIDs.PROJECT;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
index 089585b2eb3..69b71647c84 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java
@@ -85,6 +85,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.SimpleSession;
 import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE;
 import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier;
 import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomColumnTranslator;
+import ch.systemsx.cisd.openbis.generic.shared.translator.PersonTranslator;
 import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils;
 import ch.systemsx.cisd.openbis.generic.shared.util.ServerUtils;
 
@@ -627,6 +628,7 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp
         result.setUserName(session.getUserName());
         result.setUserEmail(session.getUserEmail());
         result.setAnonymous(session.isAnonymous());
+        result.setUserPersonObject(PersonTranslator.translate(person));
         return result;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/BaseEntityPropertyRecord.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/BaseEntityPropertyRecord.java
index 6367efa1d40..2afec55c049 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/BaseEntityPropertyRecord.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/BaseEntityPropertyRecord.java
@@ -1,6 +1,5 @@
 package ch.systemsx.cisd.openbis.generic.server.business.bo.common;
 
-
 /**
  * A record object for a sample property.
  */
@@ -9,7 +8,8 @@ public class BaseEntityPropertyRecord
     public long entity_id;
 
     public long prty_id;
-    
+
     public Long script_id;
-    
+
+    public String script_type;
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/EntityPropertiesEnricher.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/EntityPropertiesEnricher.java
index ba827c7ac92..f204e421bf4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/EntityPropertiesEnricher.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/common/EntityPropertiesEnricher.java
@@ -29,6 +29,7 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Material;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialEntityProperty;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.MaterialType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.PropertyType;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.ScriptType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTerm;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.VocabularyTermEntityProperty;
 
@@ -124,6 +125,7 @@ public final class EntityPropertiesEnricher implements IEntityPropertiesEnricher
             property.setValue(val.value);
             property.setPropertyType(propertyTypes.get(val.prty_id));
             property.setScriptable(val.script_id != null);
+            property.setDynamic(ScriptType.DYNAMIC_PROPERTY.name().equals(val.script_type));
             entity.getProperties().add(property);
         }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
index 8ec3ac7b9cc..7962debb9ff 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/datasetlister/IDatasetListingQuery.java
@@ -245,9 +245,10 @@ public interface IDatasetListingQuery extends TransactionQuery, IPropertyListing
      * 
      * @param entityIds The set of sample ids to get the property values for.
      */
-    @Select(sql = "SELECT pr.ds_id as entity_id, etpt.prty_id, etpt.script_id, pr.value "
+    @Select(sql = "SELECT pr.ds_id as entity_id, etpt.prty_id, etpt.script_id, pr.value, sc.script_type "
             + "      FROM data_set_properties pr"
             + "      JOIN data_set_type_property_types etpt ON pr.dstpt_id=etpt.id"
+            + "      LEFT OUTER JOIN scripts sc ON etpt.script_id = sc.id"
             + "     WHERE pr.value is not null AND pr.ds_id = any(?{1})", parameterBindings =
         { LongSetMapper.class }, fetchSize = FETCH_SIZE)
     public DataIterator<GenericEntityPropertyRecord> getEntityPropertyGenericValues(
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/materiallister/IMaterialListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/materiallister/IMaterialListingQuery.java
index 57875909cc5..f19fc7affe4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/materiallister/IMaterialListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/materiallister/IMaterialListingQuery.java
@@ -80,9 +80,10 @@ public interface IMaterialListingQuery extends TransactionQuery, IPropertyListin
      * 
      * @param entityIds The set of material ids to get the property values for.
      */
-    @Select(sql = "SELECT pr.mate_id as entity_id, etpt.prty_id, etpt.script_id, pr.value "
+    @Select(sql = "SELECT pr.mate_id as entity_id, etpt.prty_id, etpt.script_id, pr.value, sc.script_type "
             + "      FROM material_properties pr"
             + "      JOIN material_type_property_types etpt ON pr.mtpt_id=etpt.id"
+            + "      LEFT OUTER JOIN scripts sc ON etpt.script_id = sc.id"
             + "     WHERE pr.value is not null AND pr.mate_id = any(?{1})", parameterBindings =
         { LongSetMapper.class }, fetchSize = FETCH_SIZE)
     public DataIterator<GenericEntityPropertyRecord> getEntityPropertyGenericValues(
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java
index d5530d4e120..109ca510c40 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/samplelister/ISampleListingQuery.java
@@ -388,9 +388,10 @@ public interface ISampleListingQuery extends TransactionQuery, IPropertyListingQ
      * 
      * @param sampleIds The set of sample ids to get the property values for.
      */
-    @Select(sql = "SELECT sp.samp_id as entity_id, stpt.prty_id, stpt.script_id, sp.value "
+    @Select(sql = "SELECT sp.samp_id as entity_id, stpt.prty_id, stpt.script_id, sp.value, sc.script_type "
             + "      FROM sample_properties sp"
             + "      JOIN sample_type_property_types stpt ON sp.stpt_id=stpt.id"
+            + "      LEFT OUTER JOIN scripts sc ON stpt.script_id = sc.id"
             + "     WHERE sp.value is not null AND sp.samp_id = any(?{1})", parameterBindings =
         { LongSetMapper.class }, fetchSize = FETCH_SIZE)
     public DataIterator<GenericEntityPropertyRecord> getEntityPropertyGenericValues(
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractEntityProperty.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractEntityProperty.java
index df9eb401234..fe2d078ffa0 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractEntityProperty.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/AbstractEntityProperty.java
@@ -33,9 +33,11 @@ public abstract class AbstractEntityProperty implements IEntityProperty
     private PropertyType propertyType;
 
     private Long ordinal;
-    
+
     private boolean scriptable;
 
+    private boolean dynamic;
+
     @Override
     public PropertyType getPropertyType()
     {
@@ -142,6 +144,17 @@ public abstract class AbstractEntityProperty implements IEntityProperty
         return scriptable;
     }
 
+    @Override
+    public boolean isDynamic()
+    {
+        return dynamic;
+    }
+
+    public void setDynamic(boolean dynamic)
+    {
+        this.dynamic = dynamic;
+    }
+
     //
     // Object
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IEntityProperty.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IEntityProperty.java
index 7181b6f59ce..1e202f4a3e5 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IEntityProperty.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/IEntityProperty.java
@@ -57,6 +57,8 @@ public interface IEntityProperty extends Serializable, Comparable<IEntityPropert
 
     boolean isManaged();
 
+    boolean isDynamic();
+
     boolean isScriptable();
 
 }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedEntityProperty.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedEntityProperty.java
index d60220c3da1..214dcc52504 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedEntityProperty.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/ManagedEntityProperty.java
@@ -69,7 +69,7 @@ public class ManagedEntityProperty implements IEntityProperty, IManagedProperty
     {
         return entityProperty.getPropertyType().getCode();
     }
-    
+
     @Override
     public boolean isSpecialValue()
     {
@@ -91,7 +91,13 @@ public class ManagedEntityProperty implements IEntityProperty, IManagedProperty
     {
         return true;
     }
-    
+
+    @Override
+    public boolean isDynamic()
+    {
+        return false;
+    }
+
     //
     // IEntityProperty delegated methods
     //
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java
index 267cebf5615..40f4ec170df 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/dto/TableModelColumnHeader.java
@@ -49,6 +49,8 @@ public class TableModelColumnHeader implements Serializable
 
     private boolean editable;
 
+    private boolean dynamicProperty;
+
     private boolean linkEntitiesOnly;
 
     protected Vocabulary vocabularyOrNull;
@@ -154,6 +156,16 @@ public class TableModelColumnHeader implements Serializable
         return editable;
     }
 
+    public void setDynamicProperty(boolean dynamicProperty)
+    {
+        this.dynamicProperty = dynamicProperty;
+    }
+
+    public boolean isDynamicProperty()
+    {
+        return dynamicProperty;
+    }
+
     public void setLinkEntitiesOnly(boolean linkEntitiesOnly)
     {
         this.linkEntitiesOnly = linkEntitiesOnly;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SessionContextDTO.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SessionContextDTO.java
index 7e052b92ca7..c523ba6d688 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SessionContextDTO.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/dto/SessionContextDTO.java
@@ -20,6 +20,7 @@ import java.io.Serializable;
 
 import ch.systemsx.cisd.openbis.generic.shared.IServer;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DisplaySettings;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Person;
 
 /**
  * An extract from the Session object, used internally on the server side.
@@ -44,6 +45,8 @@ public class SessionContextDTO implements Serializable
 
     private boolean isAnonymous;
 
+    private Person userPersonObject;
+
     public void setSessionToken(String sessionToken)
     {
         this.sessionToken = sessionToken;
@@ -114,4 +117,13 @@ public class SessionContextDTO implements Serializable
         this.isAnonymous = isAnonymous;
     }
 
+    public void setUserPersonObject(Person userPersonObject)
+    {
+        this.userPersonObject = userPersonObject;
+    }
+
+    public Person getUserPersonObject()
+    {
+        return userPersonObject;
+    }
 }
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/PropertyTranslatorUtils.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/PropertyTranslatorUtils.java
index 9cb238b01a3..f61cd4d373c 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/PropertyTranslatorUtils.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/translator/PropertyTranslatorUtils.java
@@ -68,6 +68,7 @@ final class PropertyTranslatorUtils
         final DataTypeCode typeCode = PropertyTranslatorUtils.getDataTypeCode(propertyPE);
         final AbstractEntityProperty basicProperty = createEntityProperty(typeCode);
         basicProperty.setScriptable(propertyPE.getEntityTypePropertyType().isScriptable());
+        basicProperty.setDynamic(propertyPE.getEntityTypePropertyType().isDynamic());
         return basicProperty;
     }
 
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java
index 64ac5119c5d..d2f6966d3d4 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/IColumn.java
@@ -59,6 +59,11 @@ public interface IColumn
      */
     public IColumn editable();
 
+    /**
+     * Sets dynamic property flag to <code>true</code>.
+     */
+    public IColumn dynamicProperty();
+
     /**
      * Sets the vocabulary for controlled vocabulary property type
      */
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java
index f1377d6f15a..13b825c2b7f 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/TypedTableModelBuilder.java
@@ -253,6 +253,7 @@ public class TypedTableModelBuilder<T extends Serializable>
                         value = DataTypeUtils.convertTo(dataType, property.tryGetAsString());
                 }
                 setEditableFlag(column, propertyType);
+                setDynamicFlag(column, property);
                 column.addValue(value);
             }
         }
@@ -269,6 +270,14 @@ public class TypedTableModelBuilder<T extends Serializable>
             }
         }
 
+        private void setDynamicFlag(IColumn column, IEntityProperty property)
+        {
+            if (property.isDynamic())
+            {
+                column.dynamicProperty();
+            }
+        }
+
         private void setVocabulary(IColumn column, Vocabulary vocabularyOrNull)
         {
             column.setVocabulary(vocabularyOrNull);
@@ -341,6 +350,13 @@ public class TypedTableModelBuilder<T extends Serializable>
             return this;
         }
 
+        @Override
+        public IColumn dynamicProperty()
+        {
+            header.setDynamicProperty(true);
+            return this;
+        }
+
         @Override
         public IColumn property(String key, String value)
         {
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/css/openbis.css b/openbis/source/java/ch/systemsx/cisd/openbis/public/css/openbis.css
index cdaf17cfa8e..f46937cd134 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/public/css/openbis.css
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/public/css/openbis.css
@@ -314,3 +314,16 @@ body,div,td,.default-text {
 .linkDataViewLabel {
 	margin-right: 5px;	
 }
+
+/*************************
+ * Outdated grid cells
+ *************************/
+
+.cisd-grid-outdated-cell {
+  background: transparent no-repeat 0 0;
+  color: gray;
+}
+
+.cisd-grid-outdated-cell {
+  background-image: url(../images/outdated.gif);
+}
\ No newline at end of file
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/public/images/outdated.gif b/openbis/source/java/ch/systemsx/cisd/openbis/public/images/outdated.gif
new file mode 100644
index 0000000000000000000000000000000000000000..e2030606c0c6c3744482eb4d690f4f641de1482f
GIT binary patch
literal 832
zcmZ?wbhEHb<YM4r_|Cv^WsTJT|Nj|A!DtAK$PiHc$->CMz{sEj@;xX|FmT8+Fmi}U
gEJ!%m$iO2dv!WpJP#e3V*Bp<Hi;i|OGBQ{L05aARegFUf

literal 0
HcmV?d00001

-- 
GitLab