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 b27e94c5e64201c70b0fc573959be7ea4a203325..4ecb7f7083451a23a0fa9ac8f101fd34cea2ba30 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 @@ -16,28 +16,6 @@ package ch.systemsx.cisd.openbis.generic.server; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -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.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; - -import org.springframework.dao.DataAccessException; -import org.springframework.dao.DataIntegrityViolationException; - import ch.systemsx.cisd.authentication.IAuthenticationService; import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; import ch.systemsx.cisd.common.exceptions.UserFailureException; @@ -62,83 +40,15 @@ import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.AbstractT import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.AbstractTechIdCollectionPredicate.SpaceTechIdCollectionPredicate; import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.AbstractTechIdPredicate.ExperimentTechIdPredicate; import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.AbstractTechIdPredicate.ProjectTechIdPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.BasicEntityDescriptionPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DataSetCodeCollectionPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DataSetCodePredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DataSetTechIdPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DataSetUpdatesPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.DeletionTechIdCollectionPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ExperimentUpdatesPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ListSampleCriteriaPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectIdentifierPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectPermIdStringPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.ProjectUpdatesPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.RevertDeletionPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleTechIdCollectionReadWritePredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleTechIdPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleTechIdReadWritePredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SampleUpdatesPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SpaceIdentifierPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.SpaceUpdatesPredicate; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.DeletionValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.EntityHistoryValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.ExperimentByIdentiferValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.ExpressionValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.ExternalDataValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.MatchingEntityValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.ProjectValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SampleValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SearchDomainSearchResultValidator; -import ch.systemsx.cisd.openbis.generic.server.authorization.validator.SimpleSpaceOrProjectValidator; +import ch.systemsx.cisd.openbis.generic.server.authorization.predicate.*; +import ch.systemsx.cisd.openbis.generic.server.authorization.validator.*; import ch.systemsx.cisd.openbis.generic.server.business.IPropertiesBatchManager; -import ch.systemsx.cisd.openbis.generic.server.business.bo.DataAccessExceptionTranslator; -import ch.systemsx.cisd.openbis.generic.server.business.bo.EntityCodeGenerator; -import ch.systemsx.cisd.openbis.generic.server.business.bo.EntityTypeBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IAttachmentBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IAuthorizationGroupBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ICorePluginTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataSetTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IDataStoreBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IDeletedDataSetTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IDeletionTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IEntityTypeBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IEntityTypePropertyTypeBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IGridCustomFilterOrColumnBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IMetaprojectBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IPropertyTypeBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IPropertyTypeTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IScriptBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ISearchDomainSearcher; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ISpaceBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.ITrashBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyBO; -import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyTermBO; +import ch.systemsx.cisd.openbis.generic.server.business.bo.*; import ch.systemsx.cisd.openbis.generic.server.business.bo.common.DatabaseContextUtils; import ch.systemsx.cisd.openbis.generic.server.business.bo.datasetlister.IDatasetLister; import ch.systemsx.cisd.openbis.generic.server.business.bo.materiallister.IMaterialLister; import ch.systemsx.cisd.openbis.generic.server.business.bo.samplelister.ISampleLister; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDAOFactory; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDataStoreDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IDeletionDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityHistoryDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IEntityTypeDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IExternalDataManagementSystemDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IFileFormatTypeDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IMetaprojectDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.IRoleAssignmentDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.ISampleDAO; -import ch.systemsx.cisd.openbis.generic.server.dataaccess.RelatedEntityFinder; +import ch.systemsx.cisd.openbis.generic.server.dataaccess.*; import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.HibernateSearchDataProvider; import ch.systemsx.cisd.openbis.generic.server.dataaccess.db.SampleDataAccessExceptionTranslator; import ch.systemsx.cisd.openbis.generic.server.dataaccess.dynamic_property.DynamicPropertyEvaluator; @@ -155,14 +65,9 @@ import ch.systemsx.cisd.openbis.generic.server.jython.api.v1.impl.MasterDataRegi import ch.systemsx.cisd.openbis.generic.shared.ICommonServer; import ch.systemsx.cisd.openbis.generic.shared.IOpenBisSessionManager; import ch.systemsx.cisd.openbis.generic.shared.api.v1.dto.SearchDomain; -import ch.systemsx.cisd.openbis.generic.shared.basic.BasicEntityInformationHolder; -import ch.systemsx.cisd.openbis.generic.shared.basic.CodeConverter; -import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolder; -import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithIdentifier; -import ch.systemsx.cisd.openbis.generic.shared.basic.IEntityInformationHolderWithPermId; -import ch.systemsx.cisd.openbis.generic.shared.basic.IIdHolder; -import ch.systemsx.cisd.openbis.generic.shared.basic.IdentifierExtractor; -import ch.systemsx.cisd.openbis.generic.shared.basic.TechId; +import ch.systemsx.cisd.openbis.generic.shared.basic.*; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.Code; +import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewDataSet; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.*; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.RoleWithHierarchy.RoleCode; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedInputWidgetDescription; @@ -171,88 +76,23 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IManagedUiAction; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.api.IPerson; import ch.systemsx.cisd.openbis.generic.shared.basic.dto.id.metaproject.IMetaprojectId; import ch.systemsx.cisd.openbis.generic.shared.coreplugin.ICorePluginResourceLoader; -import ch.systemsx.cisd.openbis.generic.shared.dto.AbstractEntityPropertyHistoryPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentHolderPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.AttachmentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.AuthorizationGroupPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataSetUploadContext; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStorePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataStoreServicePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DataTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.DeletionPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.EntityPropertyPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.EntityTypePropertyTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.ExperimentUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.ExternalDataManagementSystemPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.FileFormatTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.GridCustomFilterPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.IEntityInformationHolderDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.IEntityInformationWithPropertiesHolder; -import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.MaterialUpdateDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.MetaprojectAssignmentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.MetaprojectPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.NewRoleAssignment; -import ch.systemsx.cisd.openbis.generic.shared.dto.PersonPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.ProjectUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.PropertyTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.RoleAssignmentPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.SamplePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.SampleTypePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.SampleUpdatesDTO; -import ch.systemsx.cisd.openbis.generic.shared.dto.ScriptPE; -import ch.systemsx.cisd.openbis.generic.shared.dto.SearchableEntity; -import ch.systemsx.cisd.openbis.generic.shared.dto.Session; -import ch.systemsx.cisd.openbis.generic.shared.dto.SpacePE; -import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyPE; import ch.systemsx.cisd.openbis.generic.shared.dto.VocabularyTermWithStats; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifier; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ExperimentIdentifierFactory; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifier; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.ProjectIdentifierFactory; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifierFactory; -import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SpaceIdentifier; +import ch.systemsx.cisd.openbis.generic.shared.dto.*; +import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.*; import ch.systemsx.cisd.openbis.generic.shared.hotdeploy_plugins.api.IEntityAdaptor; import ch.systemsx.cisd.openbis.generic.shared.managed_property.IManagedPropertyEvaluatorFactory; import ch.systemsx.cisd.openbis.generic.shared.managed_property.api.IManagedPropertyEvaluator; -import ch.systemsx.cisd.openbis.generic.shared.translator.AttachmentTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.AuthorizationGroupTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.DataSetTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.DataSetTypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.DataStoreServiceTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.DataStoreTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.DataTypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.DtoConverters; -import ch.systemsx.cisd.openbis.generic.shared.translator.EntityHistoryTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.EntityTypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.ExperimentTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.ExternalDataManagementSystemTranslator; +import ch.systemsx.cisd.openbis.generic.shared.translator.*; import ch.systemsx.cisd.openbis.generic.shared.translator.GridCustomExpressionTranslator.GridCustomFilterTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.MaterialTypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.MetaprojectTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.PersonTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.ProjectTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.PropertyTypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.RoleAssignmentTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.SampleTypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.ScriptTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.SpaceTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.TypeTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTermTranslator; -import ch.systemsx.cisd.openbis.generic.shared.translator.VocabularyTranslator; import ch.systemsx.cisd.openbis.generic.shared.util.EntityHelper; import ch.systemsx.cisd.openbis.generic.shared.util.HibernateUtils; import ch.systemsx.cisd.openbis.generic.shared.util.RelationshipUtils; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.DataIntegrityViolationException; + +import java.net.UnknownHostException; +import java.util.*; +import java.util.Map.Entry; public final class CommonServer extends AbstractCommonServer<ICommonServerForInternalUse> implements ICommonServerForInternalUse @@ -923,7 +763,7 @@ public final class CommonServer extends AbstractCommonServer<ICommonServerForInt { extractAssignments(result, entityTypeOrNull, propertyType); } - Collections.sort(result); + result.sort(null); return result; } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java index 80ab6d91d7c923d2ad6069ac23315d95be30e87b..3416d16c13051a66faa0542a7bdfd38f2f0a08c1 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/basic/BasicConstant.java @@ -93,7 +93,7 @@ public class BasicConstant /** * Canonical date format pattern used to render dates in GUI in a more readable way. */ - public static final String RENDERED_CANONICAL_DATE_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss ZZZZ"; + public static final String RENDERED_CANONICAL_DATE_FORMAT_PATTERN = "yyyy-MM-dd HH:mm:ss ZZZ"; /** * Date format which does not include time zone. diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidator.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidator.java index b51495b33dec850f4d040ebc228482c1c6332b30..ff379c7812a5816b7be73c936ea2439f8bc248d7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidator.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidator.java @@ -18,7 +18,6 @@ package ch.systemsx.cisd.openbis.generic.shared.util; import java.text.ParseException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Date; import java.util.EnumMap; import java.util.List; @@ -52,6 +51,10 @@ public class SimplePropertyValidator SECONDS_DATE_PATTERN("yyyy-MM-dd HH:mm:ss"), + ISO_MINUTES_DATE_PATTERN("yyyy-MM-dd'T'HH:mm"), + + ISO_SECONDS_DATE_PATTERN("yyyy-MM-dd'T'HH:mm:ss"), + US_DATE_PATTERN("M/d/yy"), US_DATE_TIME_PATTERN("M/d/yy h:mm a"), @@ -60,7 +63,11 @@ public class SimplePropertyValidator CANONICAL_DATE_PATTERN(BasicConstant.CANONICAL_DATE_FORMAT_PATTERN), - RENDERED_CANONICAL_DATE_PATTERN(BasicConstant.RENDERED_CANONICAL_DATE_FORMAT_PATTERN); + ISO_CANONICAL_DATE_PATTERN("yyyy-MM-dd'T'HH:mm:ssX"), + + RENDERED_CANONICAL_DATE_PATTERN(BasicConstant.RENDERED_CANONICAL_DATE_FORMAT_PATTERN), + + ISO_RENDERED_CANONICAL_DATE_PATTERN("yyyy-MM-dd'T'HH:mm:ssXXX"); private final String pattern; @@ -199,7 +206,7 @@ public class SimplePropertyValidator // we store date in CANONICAL_DATE_PATTERN return DateFormatUtils.format(date, SupportedDatePattern.CANONICAL_DATE_PATTERN.getPattern()); - } catch (final ParseException ex) + } catch (final ParseException | IllegalArgumentException ex) { throwUserFailureException(value); return null; @@ -209,7 +216,7 @@ public class SimplePropertyValidator /** * Manually validates the date value on cases which are omitted by DateUtils. * - * @param value the date-time value to validate. + * @param value the date-time value to validate. * @throws UserFailureException thrown if the value is not considered as a well formatted date. */ private void validateHyphens(final String value) throws UserFailureException @@ -218,18 +225,15 @@ public class SimplePropertyValidator { return; } - - final String dateValue = extractDate(value); - final boolean hyphenFormat = dateValue.matches("\\d*-\\d*-\\d*"); - final boolean desiredHyphenFormat = dateValue.matches("\\d{4,}-\\d+-\\d+"); - if (hyphenFormat && !desiredHyphenFormat) + int indexOfHyphen = value.indexOf('-'); + if (indexOfHyphen >= 0 && indexOfHyphen != 4) { - // When the date value uses hyphens as separators but does not have 4 digits for the year value + // When the date value uses hyphens as separators but does not have 4 digits for the year value // throw an exception. throwUserFailureException(value); } } - + /** * Throws UserFailureException. * @@ -238,21 +242,10 @@ public class SimplePropertyValidator */ private final static void throwUserFailureException(final String value) throws UserFailureException { + final String validValues = "[" + String.join("\n", DATE_PATTERNS) + "]"; throw UserFailureException.fromTemplate( "Date value '%s' has improper format. It must be one of '%s'.", value, - Arrays.toString(DATE_PATTERNS)); - } - - /** - * Extracts date part from the string representation of a date-time. - * - * @param value the value considered as string representation of date-time. - * @return the date portion of the date-time string. - */ - private final static String extractDate(final String value) - { - final int dateSeparator = Math.min(value.indexOf(' '), value.indexOf('T')); - return dateSeparator >= 0 ? value.substring(0, dateSeparator) : value; + validValues); } } diff --git a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPropertyAssignmentTest.java b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPropertyAssignmentTest.java index 841d2e743c21cf68c6aa78f0380bd815d0227188..06cbd7fe3f71bf65bc17967d88d6f029a0149a8b 100644 --- a/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPropertyAssignmentTest.java +++ b/openbis/sourceTest/java/ch/ethz/sis/openbis/systemtest/asapi/v3/SearchPropertyAssignmentTest.java @@ -219,7 +219,7 @@ public class SearchPropertyAssignmentTest extends AbstractTest Assert.assertTrue(propertyAssignment.getEntityType().getCode().equals("CELL_PLATE") || propertyAssignment.getPropertyType().getCode().equals("BACTERIUM")); } - assertEquals(propertyAssignments.size(), 11); + assertEquals(propertyAssignments.size() >= 11, true); } @Test diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java index 3b2428f37d89948c4bcfc6b74145cda9fd26f3d2..9f24cf7bb826c01cd4b1fab9590290e69652ae4e 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/client/application/AuthorizationManagementConsolTest.java @@ -16,18 +16,9 @@ package ch.systemsx.cisd.openbis.generic.client.web.client.application; -import com.google.gwt.user.client.rpc.AsyncCallback; - import ch.systemsx.cisd.openbis.generic.client.web.client.application.menu.TopMenu.ActionMenuKind; import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.TypedTableGrid; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.CheckGroupTable; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.CheckPersonTable; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.CheckRoleAssignmentTable; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.CreateGroup; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.CreatePerson; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.FillRoleAssignmentForm; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.OpenRoleAssignmentDialog; -import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.RoleAssignmentRow; +import ch.systemsx.cisd.openbis.generic.client.web.client.application.ui.amc.*; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.PersonGridColumnIDs; import ch.systemsx.cisd.openbis.generic.client.web.client.dto.SpaceGridColumnIDs; import ch.systemsx.cisd.openbis.generic.client.web.client.testframework.AbstractGWTTestCase; @@ -114,7 +105,7 @@ public class AuthorizationManagementConsolTest extends AbstractGWTTestCase FailureExpectation failureExpectation = new FailureExpectation( - (Class<? extends AsyncCallback<?>>) TypedTableGrid.ListEntitiesCallback.class) + (Class) TypedTableGrid.ListEntitiesCallback.class) .with("Authorization failure: None of method roles '[INSTANCE_ADMIN]' " + "could be found in roles of user 'o'."); diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidatorTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidatorTest.java new file mode 100644 index 0000000000000000000000000000000000000000..599b46bc2ae77f9706510f8e10557a81837b0876 --- /dev/null +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/shared/util/SimplePropertyValidatorTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2019 ETH Zuerich, SIS + * + * 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.util; + +import ch.systemsx.cisd.common.exceptions.UserFailureException; +import ch.systemsx.cisd.openbis.generic.shared.util.SimplePropertyValidator.TimestampValidator; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; + +/** + * @author Franz-Josef Elmer + */ +public class SimplePropertyValidatorTest +{ + + @DataProvider + public Object[][] validTimestamps() + { + return new Object[][]{ + {"2020-05-16", "2020-05-16 00:00:00 +0200"}, + {"2020-5-16", "2020-05-16 00:00:00 +0200"}, + {"2019-01-16", "2019-01-16 00:00:00 +0100"}, + {"2019-01-16 3:4", "2019-01-16 03:04:00 +0100"}, + {"2019-01-16 18:23:56", "2019-01-16 18:23:56 +0100"}, + {"2019-01-16 18:23:56 +0700", "2019-01-16 12:23:56 +0100"}, + {"2019-01-16 18:23:56 GMT", "2019-01-16 19:23:56 +0100"}, + {"1/16/19", "2019-01-16 00:00:00 +0100"}, + {"1/16/19 8:9", "2019-01-16 08:09:00 +0100"}, + {"1/16/19 8:9 p", "2019-01-16 20:09:00 +0100"}, + {"1/16/19 18:19", "2019-01-16 18:19:00 +0100"}, + {"2019-01-20T10:58", "2019-01-20 10:58:00 +0100"}, + {"2019-01-20T10:58:24", "2019-01-20 10:58:24 +0100"}, + {"2019-05-20T10:58:24", "2019-05-20 10:58:24 +0200"}, + {"2019-05-20T10:58:24+07:00", "2019-05-20 05:58:24 +0200"}, + {"2019-05-20T10:58:24-07:30", "2019-05-20 20:28:24 +0200"}, + {"2019-01-20T10:58:24Z", "2019-01-20 11:58:24 +0100"}, + {"2019-05-20T10:58:24Z", "2019-05-20 12:58:24 +0200"}, + }; + } + + @DataProvider + public Object[][] invalidTimestamps() + { + return new Object[][] { + { "10-05-06" }, + { "10-05-06 7:23" }, + { "10-05-06 17:13:39" }, + { "2010-05-36 17:13:39" }, + { "2010-05-06 27:13:39" }, + { "13/12/11 7:39" }, + { "3/12/11 7:39:22" }, + { "10-05-06T7:23" }, + { "10-05-06T17:13:39" }, + { "2010-05-36T17:13:39" }, + { "2010-05-06T27:13:39" }, + }; + } + + @Test(dataProvider = "validTimestamps") + public void testTimestampValidatorWithValidExamples(String stringToParse, String canonicalTimestamp) + { + TimestampValidator validator = new SimplePropertyValidator.TimestampValidator(); + + assertEquals(validator.validate(stringToParse), canonicalTimestamp); + } + + @Test(dataProvider = "invalidTimestamps") + public void testTimestampValidatorWithInvalidExamples(String stringToParse) + { + TimestampValidator validator = new SimplePropertyValidator.TimestampValidator(); + + try + { + validator.validate(stringToParse); + } catch (UserFailureException e) + { + assertEquals(e.getMessage(), "Date value '" + stringToParse + "' has improper format. " + + "It must be one of '[yyyy-MM-dd\n" + + "yyyy-MM-dd HH:mm\n" + + "yyyy-MM-dd HH:mm:ss\n" + + "yyyy-MM-dd'T'HH:mm\n" + + "yyyy-MM-dd'T'HH:mm:ss\n" + + "M/d/yy\n" + + "M/d/yy h:mm a\n" + + "M/d/yy HH:mm\n" + + "yyyy-MM-dd HH:mm:ss Z\n" + + "yyyy-MM-dd'T'HH:mm:ssX\n" + + "yyyy-MM-dd HH:mm:ss ZZZ\n" + + "yyyy-MM-dd'T'HH:mm:ssXXX]'."); + } + } + +} diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/FlowCytometryTechnology.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/FlowCytometryTechnology.js index bd6a377e9d0a6ad004ad133e75c57b232bd3b8bd..8841a7bf04bc1c2f50a6cf32391e004d6d4ef8bb 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/FlowCytometryTechnology.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/FlowCytometryTechnology.js @@ -1,744 +1,753 @@ function FlowCytometryTechnology() { - this.init(); + this.init(); } $.extend(FlowCytometryTechnology.prototype, ELNLIMSPlugin.prototype, { - init: function () { - - // Store a reference to the "retrieve FCS events" service - this.retrieveFCSEventsService = null; - - // Data cache - this.dataCache = {}; - }, - forcedDisableRTF: [], - forceMonospaceFont: [], - sampleTypeDefinitionsExtension: { - "FACS_ARIA_EXPERIMENT": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SAMPLE_PARENTS_HINT": [{ - "LABEL": "Organization Units", - "TYPE": "ORGANIZATION_UNIT", - "ANNOTATION_PROPERTIES": [] - }] - }, - "INFLUX_EXPERIMENT": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SAMPLE_PARENTS_HINT": [{ - "LABEL": "Organization Units", - "TYPE": "ORGANIZATION_UNIT", - "ANNOTATION_PROPERTIES": [] - }] - }, - "LSR_FORTESSA_EXPERIMENT": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SAMPLE_PARENTS_HINT": [{ - "LABEL": "Organization Units", - "TYPE": "ORGANIZATION_UNIT", - "ANNOTATION_PROPERTIES": [] - }] - }, - "MOFLO_XDP_EXPERIMENT": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SAMPLE_PARENTS_HINT": [{ - "LABEL": "Organization Units", - "TYPE": "ORGANIZATION_UNIT", - "ANNOTATION_PROPERTIES": [] - }] - }, - "S3E_EXPERIMENT": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SAMPLE_PARENTS_HINT": [{ - "LABEL": "Organization Units", - "TYPE": "ORGANIZATION_UNIT", - "ANNOTATION_PROPERTIES": [] - }] - }, - "FACS_ARIA_SPECIMEN": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "FACS_ARIA_TUBE": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "FACS_ARIA_TUBESET": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "INFLUX_SPECIMEN": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "INFLUX_TUBE": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "INFLUX_TUBESET": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "LSR_FORTESSA_PLATE": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "LSR_FORTESSA_SPECIMEN": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "LSR_FORTESSA_TUBE": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "LSR_FORTESSA_TUBESET": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "LSR_FORTESSA_WELL": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "MOFLO_XDP_SPECIMEN": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "MOFLO_XDP_TUBE": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "MOFLO_XDP_TUBESET": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "S3E_TUBE": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "S3E_TUBESET": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - }, - "S3E_SPECIMEN": { - "TOOLBAR": { CREATE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, - "SHOW_ON_NAV": true - } - }, - dataSetTypeDefinitionsExtension: { - "FACS_ARIA_FCSFILE": { - "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } - }, - "INFLUX_FCSFILE": { - "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } - }, - "LSR_FORTESSA_FCSFILE": { - "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } - }, - "MOFLO_XDP_FCSFILE": { - "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } - }, - "S3E_ARIA_FCSFILE": { - "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } - } - }, - sampleFormTop: function ($container, model) { - - }, - sampleFormBottom: function ($container, model) { - - }, - dataSetFormTop: function ($container, model) { - - // Render the paremeter options - this.renderParameterSelectionWidget($container, model); - - // Add a div for reporting status - $container.append($('<div>') - .css("margin-bottom", "5px") - .attr("id", "status_div")); - - // Append the div where the data will be plotted - $container.append($('<div>') - .css("width", "580px") - .attr("id", "plot_canvas_div")); - - }, - dataSetFormBottom: function ($container, model) { - - }, - - // Additional functionality - renderParameterSelectionWidget: function ($container, model) { - - // Check that we ave the correct dataset type - if (!model.dataSetV3.type.code.endsWith("_FCSFILE")) { - return; - } - - // Clear the container - $container.empty(); - - // - // Retrieve the parameter info - // - var parameterInfo = this.retrieveParameterInfo(model); - - // Add legend - var legend = $("<legend>") - .text("Data viewer") - $container.append(legend); - - // Create a div for all plotting options - var plot_params_div = $('<div>') - .css("text-align", "left") - .css("margin", "5px 0 15px 0") - .attr("id", "plot_params_div"); - - // - // Lay out the widget - // - - // Create a form for the plot parameters - var form = $("<form>") - .attr("id", "parameter_form"); - plot_params_div.append(form); - - // Create divs to spatially organize the groups of parameters - var xAxisDiv = $("<div>") - .css("display", "inline-block") - .css("text-align", "right") - .attr("id", "xAxisDiv") - var yAxisDiv = $("<div>") - .css("display", "inline-block") - .css("text-align", "right") - .attr("id", "yAxisDiv") - var eventsDiv = $("<div>") - .css("display", "inline-block") - .css("text-align", "right") - .attr("id", "eventsDiv") - var plotDiv = $("<div>") - .css("display", "inline-block") - .css("vertical-align", "top") - .css("padding-left", "10px") - .attr("id", "plotDiv") - - // Add them to the form - form.append(xAxisDiv); - form.append(yAxisDiv); - form.append(eventsDiv); - form.append(plotDiv); - - // X axis parameters - xAxisDiv.append($("<label>") - .attr("for", "parameter_form_select_X_axis") - .html("X axis")); - var selectXAxis = $("<select>") - .css("margin", "0 3px 0 3px") - .attr("id", "parameter_form_select_X_axis"); - xAxisDiv.append(selectXAxis); - - // Y axis parameters - yAxisDiv.append($("<label>") - .attr("for", "parameter_form_select_Y_axis") - .html("Y axis")); - var selectYAxis = $("<select>") - .css("margin", "0 3px 0 3px") - .attr("id", "parameter_form_select_Y_axis"); - yAxisDiv.append(selectYAxis); - - // Add all options - for (var i = 0; i < parameterInfo.numParameters; i++) { - var name = parameterInfo["names"][i]; - var compositeName = parameterInfo["compositeNames"][i]; - selectXAxis.append($("<option>") - .attr("value", name) - .text(compositeName)); - selectYAxis.append($("<option>") - .attr("value", name) - .text(compositeName)); - } - - // // Pre-select some parameters - selectXAxis.val(parameterInfo["names"][0]); - selectYAxis.val(parameterInfo["names"][1]); - - // Add a selector with the number of events to plot - eventsDiv.append($("<label>") - .attr("for", "parameter_form_select_num_events") - .html("Events to plot")); - var selectNumEvents = $("<select>") - .css("margin", "0 3px 0 3px") - .attr("id", "parameter_form_select_num_events"); - eventsDiv.append(selectNumEvents); - - // Add the options - var possibleOptions = [500, 1000, 2500, 5000, 10000, 20000, 50000, 100000]; - var numEventsInFile = parseInt(parameterInfo.numEvents); - for (var i = 0; i < possibleOptions.length; i++) { - if (possibleOptions[i] < numEventsInFile) { - selectNumEvents.append($("<option>") - .attr("value", possibleOptions[i]) - .text(possibleOptions[i].toString())); - } - } - selectNumEvents.append($("<option>") - .attr("value", parameterInfo.numEvents) - .text(parseInt(parameterInfo.numEvents))); - - // Pre-select something reasonable - if (parameterInfo.numEvents > possibleOptions[4]) { - selectNumEvents.val(parseInt(possibleOptions[4])); - } else { - selectNumEvents.val(parseInt(parameterInfo.numEvents)); - } - - // Add "Plot" button - var thisObj = this; - var plotButton = $("<input>") - .attr("type", "button") - .attr("value", "Plot") - .click(function () { - - // Get the selected parameters and their display scaling - var paramX = selectXAxis.find(":selected").val(); - var paramY = selectYAxis.find(":selected").val(); - var displayX = selectScaleX.find(":selected").val(); - var displayY = selectScaleY.find(":selected").val(); - - // How many events to plot? - var numEventsToPlot = selectNumEvents.val(); - - // Sampling method - var samplingMethod = selectSamplingMethod.find(":selected").val(); - - // Call the retrieving and plotting method - thisObj.callServerSidePluginGenerateFCSPlot( - model, - paramX, - paramY, - displayX, - displayY, - numEventsToPlot, - parameterInfo.numEvents, - samplingMethod); - }); - plotDiv.append(plotButton); - - // Add a selector with the scaling for axis X - var xAxisScalingDiv = xAxisDiv.append($("<div>") - .css("display", "block") - .attr("id", "xAxisScalingDiv")); - xAxisScalingDiv.append($("<label>") - .attr("for", "parameter_form_select_scaleX") - .html("Scale for X axis")); - var selectScaleX = $("<select>") - .css("margin", "0 3px 0 3px") - .attr("id", "parameter_form_select_scaleX"); - xAxisScalingDiv.append(selectScaleX); - - // Add the options - possibleOptions = ["Linear", "Hyperlog"]; - for (var i = 0; i < possibleOptions.length; i++) { - selectScaleX.append($("<option>") - .attr("name", possibleOptions[i]) - .attr("value", possibleOptions[i]) - .text(possibleOptions[i])); - } - - // Pre-select "Linear" - $("parameter_form_select_scaleX").val(0); - - // Add a selector with the scaling for axis Y - var yAxisScalingDiv = yAxisDiv.append($("<div>") - .css("display", "block") - .attr("id", "yAxisScalingDiv")); - yAxisScalingDiv.append($("<label>") - .attr("for", "parameter_form_select_scaleY") - .html("Scale for Y axis")); - var selectScaleY = $("<select>") - .css("margin", "0 3px 0 3px") - .attr("id", "parameter_form_select_scaleY"); - yAxisScalingDiv.append(selectScaleY); - - // Add the options - possibleOptions = ["Linear", "Hyperlog"]; - for (var i = 0; i < possibleOptions.length; i++) { - selectScaleY.append($("<option>") - .attr("name", possibleOptions[i]) - .attr("value", possibleOptions[i]) - .text(possibleOptions[i])); - } - - // Pre-select "Linear" - $("parameter_form_select_scaleY").val(0); - - // Add a selector with the sampling method - var eventSamplingDiv = eventsDiv.append($("<div>") - .css("display", "block") - .attr("id", "eventSamplingDiv")); - eventSamplingDiv.append($("<label>") - .attr("for", "parameter_form_select_sampling_method") - .html("Sampling")); - var selectSamplingMethod = $("<select>") - .css("margin", "0 3px 0 3px") - .attr("id", "parameter_form_select_sampling_method"); - eventSamplingDiv.append(selectSamplingMethod); - - // Add the options - possibleOptions = ["Regular", "First rows"]; - for (var i = 0; i < possibleOptions.length; i++) { - selectSamplingMethod.append($("<option>") - .attr("name", "" + (i + 1)) - .attr("value", (i + 1)) - .text(possibleOptions[i])); - } - - // Pre-select "Linear" - $("parameter_form_select_sampling_method").val(0); - - // - // End of widget - // - - // Append the created div to the container - $container.append(plot_params_div); - - }, - - retrieveParameterInfo: function (model) { - - // Retrieve parameter information - var key = model.dataSetV3.type.code.substring( - 0, model.dataSetV3.type.code.indexOf("_FCSFILE")) + - "_FCSFILE_PARAMETERS"; - - var parametersXML = $.parseXML(model.dataSetV3.properties[key]); - var parameters = parametersXML.childNodes[0]; - - var numParameters = parameters.getAttribute("numParameters"); - var numEvents = parameters.getAttribute("numEvents"); - - var names = []; - var compositeNames = []; - var display = []; - - // Parameter numbering starts at 1 - var parametersToDisplay = 0; - for (var i = 1; i <= numParameters; i++) { - - // If the parameter contains the PnCHANNELTYPE attribute (BD Influx Cell Sorter), - // we only add it if the channel type is 6. - var channelType = parameters.getAttribute("P" + i + "CHANNELTYPE"); - if (channelType != null && channelType !== 6) { - continue; - } - - // Store the parameter name - var name = parameters.getAttribute("P" + i + "N"); - names.push(name); - - // Store the composite name - var pStr = parameters.getAttribute("P" + i + "S"); - var composite = name; - if (pStr !== "") { - composite = name + " (" + pStr + ")"; - } - compositeNames.push(composite); - - // Store the display scale - var displ = parameters.getAttribute("P" + i + "DISPLAY"); - display.push(displ); - - // Update the count of parameters to display - parametersToDisplay++; - } - - // Store the parameter info - parameterInfo = { - "numParameters": parametersToDisplay, - "numEvents": numEvents, - "names": names, - "compositeNames": compositeNames, - "display": display - } - - // Return it - return parameterInfo; - }, - - callServerSidePluginGenerateFCSPlot: function (model, paramX, paramY, displayX, displayY, numEventsToPlot, totalNumEvents, samplingMethod) { - - // Check whether the data for the plot is already cached - var key = model.dataSetV3.code + "_" + paramX + "_" + paramY + "_" + numEventsToPlot.toString() + - "_" + displayX + "_" + displayY + "_" + samplingMethod.toString(); - - if (model.dataSetV3.code in this.dataCache && - key in this.dataCache[model.dataSetV3.code]) { - - // Plot the cached data - this.plotFCSData( - this.dataCache[model.dataSetV3.code][key], - paramX, - paramY, - displayX, - displayY); - - // Return immediately - return; - } - - // Inform the user that we are about to process the request - this.displayStatus("Please wait while processing your request. This might take a while...", - "info"); - - var thisObj = this; - require(["openbis", - "as/dto/service/search/AggregationServiceSearchCriteria", - "as/dto/service/fetchoptions/AggregationServiceFetchOptions", - "as/dto/service/execute/AggregationServiceExecutionOptions"], - function (openbis, - AggregationServiceSearchCriteria, - AggregationServiceFetchOptions, - AggregationServiceExecutionOptions) { - - // Parameters for the aggregation service - var options = new AggregationServiceExecutionOptions(); - options.withParameter("code", model.dataSetV3.code); - options.withParameter("paramX", paramX); - options.withParameter("paramY", paramY); - options.withParameter("displayX", displayX); - options.withParameter("displayY", displayY); - options.withParameter("numEvents", totalNumEvents); - options.withParameter("maxNumEvents", numEventsToPlot); - options.withParameter("samplingMethod", samplingMethod); - options.withParameter("nodeKey", model.dataSetV3.code); - - // Call service - if (null === thisObj.retrieveFCSEventsService) { - var criteria = new AggregationServiceSearchCriteria(); - criteria.withName().thatEquals("retrieve_fcs_events"); - var fetchOptions = new AggregationServiceFetchOptions(); - mainController.openbisV3.searchAggregationServices(criteria, fetchOptions).then(function (result) { - - // Check that we got our service - if (undefined === result.objects) { - console.log("Could not retrieve the server-side aggregation service!"); - return; - } - thisObj.retrieveFCSEventsService = result.getObjects()[0]; - - // Now call the service - mainController.openbisV3.executeAggregationService( - thisObj.retrieveFCSEventsService.getPermId(), - options).then(function (result) { - thisObj.processResultsFromRetrieveFCSEventsServerSidePlugin(result); - }); - }); - } else { - // Call the service - mainController.openbisV3.executeAggregationService( - thisObj.retrieveFCSEventsService.getPermId(), - options).then(function (result) { - thisObj.processResultsFromRetrieveFCSEventsServerSidePlugin(result); - }); - } - }); - }, - - plotFCSData: function (data, xLabel, yLabel, xDisplay, yDisplay) { - - // Make sure to have a proper array - var parsed_data = JSON.parse(data); - - // Prepend data names to be compatible with C3.js - parsed_data[0].unshift("x_values"); - parsed_data[1].unshift("y_values"); - - // Plot the data - c3.generate({ - bindto: '#plot_canvas_div', - title: { - text: yLabel + " vs. " + xLabel - }, - data: { - xs: { - y_values: "x_values" - }, - columns: [ - parsed_data[0], - parsed_data[1], - ], - names: { - y_values: yLabel - }, - type: 'scatter' - }, - axis: { - x: { - label: xLabel, - tick: { - fit: false - } - }, - y: { - label: yLabel, - tick: { - fit: false - } - } - }, - legend: { - show: false - }, - tooltip: { - format: { - title: function (d) { - const format = d3.format(','); - return xLabel + " | " + format(d); - }, - value: function (value, ratio, id) { - const format = d3.format(','); - return format(value); - } - } - }, - zoom: { - enabled: true, - rescale: true - }, - }); - }, - - processResultsFromRetrieveFCSEventsServerSidePlugin: function (table) { - - // Did we get the expected result? - if (!table.rows || table.rows.length !== 1) { - DATAVIEWER.displayStatus( - "There was an error retrieving the data to plot!", - "danger"); - return; - } - - // Get the row of results - var row = table.rows[0]; - - // Retrieve the uid - var r_UID = row[0].value; - - // Is the process completed? - var r_Completed = row[1].value; - - var thisObj = this; - if (r_Completed === 0) { - - require(["as/dto/service/execute/AggregationServiceExecutionOptions"], - function (AggregationServiceExecutionOptions) { - - // Call the plug-in - setTimeout(function () { - - // Now call the service again: - // we only need the UID of the job - var options = new AggregationServiceExecutionOptions(); - options.withParameter("uid", r_UID); - - mainController.openbisV3.executeAggregationService( - thisObj.retrieveFCSEventsService.getPermId(), - options).then(function (result) { - thisObj.processResultsFromRetrieveFCSEventsServerSidePlugin(result); - }) - }, 2000); - }); - - // Return here - return; - - } - - // We completed the call and we can process the result - - // Returned parameters - var r_Success = row[2].value; - var r_ErrorMessage = row[3].value; - var r_Data = row[4].value; - var r_Code = row[5].value; - var r_ParamX = row[6].value; - var r_ParamY = row[7].value; - var r_DisplayX = row[8].value; - var r_DisplayY = row[9].value; - var r_NumEvents = row[10].value; // Currently not used - var r_MaxNumEvents = row[11].value; - var r_SamplingMethod = row[12].value; - var r_NodeKey = row[13].value; - - var level; - if (r_Success === 1) { - - // Error message and level - status = r_ErrorMessage; - level = "success"; - - // Plot the data - thisObj.plotFCSData(r_Data, r_ParamX, r_ParamY, r_DisplayX, r_DisplayY); - - // Cache the plotted data - var dataKey = r_Code + "_" + r_ParamX + "_" + r_ParamY + "_" + r_MaxNumEvents.toString() + - "_" + r_DisplayX + "_" + r_DisplayY + "_" + r_SamplingMethod.toString(); - thisObj.cacheFCSData(r_NodeKey, dataKey, r_Data); - - } else { - status = "Sorry, there was an error: \"" + r_ErrorMessage + "\"."; - level = "danger"; - } - - // We only display errors - if (r_Success === 0) { - thisObj.displayStatus(status, level); - } else { - thisObj.hideStatus(); - } - - return table; - - }, - - cacheFCSData: function (nodeKey, dataKey, fcsData) { - - // Cache the data - if (! (nodeKey in this.dataCache)) { - this.dataCache[nodeKey] = {}; - } - this.dataCache[nodeKey][dataKey] = fcsData; - }, - - displayStatus: function(status, level) { - switch (level) { - case "info": - color = "black"; - break; - case "success": - color = "cyan"; - break; - case "danger": - color = "red"; - break; - default: - color = "black"; - break; - } - var status_div = $("#status_div"); - status_div - .css("color", color) - .text(status); - status_div.show(); - }, - - hideStatus: function() { - $("#status_div").hide(); - } + init: function () { + + // Store a reference to the "retrieve FCS events" service + this.retrieveFCSEventsService = null; + + // Data cache + this.dataCache = {}; + }, + forcedDisableRTF: [], + forceMonospaceFont: [], + sampleTypeDefinitionsExtension: { + "FACS_ARIA_EXPERIMENT": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SAMPLE_CHILDREN_DISABLED": true, + "SAMPLE_PARENTS_HINT": [{ + "LABEL": "Organization Units", + "TYPE": "ORGANIZATION_UNIT", + "ANNOTATION_PROPERTIES": [] + }] + }, + "INFLUX_EXPERIMENT": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SAMPLE_CHILDREN_DISABLED": true, + "SAMPLE_PARENTS_HINT": [{ + "LABEL": "Organization Units", + "TYPE": "ORGANIZATION_UNIT", + "ANNOTATION_PROPERTIES": [] + }] + }, + "LSR_FORTESSA_EXPERIMENT": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SAMPLE_CHILDREN_DISABLED": true, + "SAMPLE_PARENTS_HINT": [{ + "LABEL": "Organization Units", + "TYPE": "ORGANIZATION_UNIT", + "ANNOTATION_PROPERTIES": [] + }] + }, + "MOFLO_XDP_EXPERIMENT": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SAMPLE_CHILDREN_DISABLED": true, + "SAMPLE_PARENTS_HINT": [{ + "LABEL": "Organization Units", + "TYPE": "ORGANIZATION_UNIT", + "ANNOTATION_PROPERTIES": [] + }] + }, + "S3E_EXPERIMENT": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SAMPLE_CHILDREN_DISABLED": true, + "SAMPLE_PARENTS_HINT": [{ + "LABEL": "Organization Units", + "TYPE": "ORGANIZATION_UNIT", + "ANNOTATION_PROPERTIES": [] + }] + }, + "FACS_ARIA_SPECIMEN": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "FACS_ARIA_TUBE": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "FACS_ARIA_TUBESET": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "INFLUX_SPECIMEN": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "INFLUX_TUBE": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "INFLUX_TUBESET": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "LSR_FORTESSA_PLATE": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "LSR_FORTESSA_SPECIMEN": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "LSR_FORTESSA_TUBE": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "LSR_FORTESSA_TUBESET": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "LSR_FORTESSA_WELL": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "MOFLO_XDP_SPECIMEN": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "MOFLO_XDP_TUBE": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "MOFLO_XDP_TUBESET": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "S3E_TUBE": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "S3E_TUBESET": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + }, + "S3E_SPECIMEN": { + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: false, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "SHOW_ON_NAV": true + } + }, + dataSetTypeDefinitionsExtension: { + "FACS_ARIA_FCSFILE": { + "DATASET_PARENTS_DISABLED": true, + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + }, + "INFLUX_FCSFILE": { + "DATASET_PARENTS_DISABLED": true, + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + }, + "LSR_FORTESSA_FCSFILE": { + "DATASET_PARENTS_DISABLED": true, + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + }, + "MOFLO_XDP_FCSFILE": { + "DATASET_PARENTS_DISABLED": true, + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + }, + "S3E_ARIA_FCSFILE": { + "DATASET_PARENTS_DISABLED": true, + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + } + }, + sampleFormTop: function ($container, model) { + + }, + sampleFormBottom: function ($container, model) { + + }, + dataSetFormTop: function ($container, model) { + + // Render the paremeter options + this.renderParameterSelectionWidget($container, model); + + // Add a div for reporting status + $container.append($('<div>') + .css("margin-bottom", "5px") + .attr("id", "status_div")); + + // Append the div where the data will be plotted + $container.append($('<div>') + .css("width", "580px") + .attr("id", "plot_canvas_div")); + + }, + dataSetFormBottom: function ($container, model) { + + }, + + // Additional functionality + renderParameterSelectionWidget: function ($container, model) { + + // Check that we ave the correct dataset type + if (!model.dataSetV3) { + return; + } + + if (!model.dataSetV3.type.code.endsWith("_FCSFILE")) { + return; + } + + // Clear the container + $container.empty(); + + // + // Retrieve the parameter info + // + var parameterInfo = this.retrieveParameterInfo(model); + + // Add legend + var legend = $("<legend>") + .text("Data viewer"); + $container.append(legend); + + // Create a div for all plotting options + var plot_params_div = $('<div>') + .css("text-align", "left") + .css("margin", "5px 0 15px 0") + .attr("id", "plot_params_div"); + + // + // Lay out the widget + // + + // Create a form for the plot parameters + var form = $("<form>") + .attr("id", "parameter_form"); + plot_params_div.append(form); + + // Create divs to spatially organize the groups of parameters + var xAxisDiv = $("<div>") + .css("display", "inline-block") + .css("text-align", "right") + .attr("id", "xAxisDiv"); + var yAxisDiv = $("<div>") + .css("display", "inline-block") + .css("text-align", "right") + .attr("id", "yAxisDiv"); + var eventsDiv = $("<div>") + .css("display", "inline-block") + .css("text-align", "right") + .attr("id", "eventsDiv"); + var plotDiv = $("<div>") + .css("display", "inline-block") + .css("vertical-align", "top") + .css("padding-left", "10px") + .attr("id", "plotDiv"); + + // Add them to the form + form.append(xAxisDiv); + form.append(yAxisDiv); + form.append(eventsDiv); + form.append(plotDiv); + + // X axis parameters + xAxisDiv.append($("<label>") + .attr("for", "parameter_form_select_X_axis") + .html("X axis")); + var selectXAxis = $("<select>") + .css("margin", "0 3px 0 3px") + .attr("id", "parameter_form_select_X_axis"); + xAxisDiv.append(selectXAxis); + + // Y axis parameters + yAxisDiv.append($("<label>") + .attr("for", "parameter_form_select_Y_axis") + .html("Y axis")); + var selectYAxis = $("<select>") + .css("margin", "0 3px 0 3px") + .attr("id", "parameter_form_select_Y_axis"); + yAxisDiv.append(selectYAxis); + + // Add all options + for (var i = 0; i < parameterInfo.numParameters; i++) { + var name = parameterInfo["names"][i]; + var compositeName = parameterInfo["compositeNames"][i]; + selectXAxis.append($("<option>") + .attr("value", name) + .text(compositeName)); + selectYAxis.append($("<option>") + .attr("value", name) + .text(compositeName)); + } + + // // Pre-select some parameters + selectXAxis.val(parameterInfo["names"][0]); + selectYAxis.val(parameterInfo["names"][1]); + + // Add a selector with the number of events to plot + eventsDiv.append($("<label>") + .attr("for", "parameter_form_select_num_events") + .html("Events to plot")); + var selectNumEvents = $("<select>") + .css("margin", "0 3px 0 3px") + .attr("id", "parameter_form_select_num_events"); + eventsDiv.append(selectNumEvents); + + // Add the options + var possibleOptions = [500, 1000, 2500, 5000, 10000, 20000, 50000, 100000]; + var numEventsInFile = parseInt(parameterInfo.numEvents); + for (i = 0; i < possibleOptions.length; i++) { + if (possibleOptions[i] < numEventsInFile) { + selectNumEvents.append($("<option>") + .attr("value", possibleOptions[i]) + .text(possibleOptions[i].toString())); + } + } + selectNumEvents.append($("<option>") + .attr("value", parameterInfo.numEvents) + .text(parseInt(parameterInfo.numEvents))); + + // Pre-select something reasonable + if (parameterInfo.numEvents > possibleOptions[4]) { + selectNumEvents.val(possibleOptions[4]); + } else { + selectNumEvents.val(parameterInfo.numEvents); + } + + // Add "Plot" button + var thisObj = this; + var plotButton = $("<input>") + .attr("type", "button") + .attr("value", "Plot") + .click(function () { + + // Get the selected parameters and their display scaling + var paramX = selectXAxis.find(":selected").val(); + var paramY = selectYAxis.find(":selected").val(); + var displayX = selectScaleX.find(":selected").val(); + var displayY = selectScaleY.find(":selected").val(); + + // How many events to plot? + var numEventsToPlot = selectNumEvents.val(); + + // Sampling method + var samplingMethod = selectSamplingMethod.find(":selected").val(); + + // Call the retrieving and plotting method + thisObj.callServerSidePluginGenerateFCSPlot( + model, + paramX, + paramY, + displayX, + displayY, + numEventsToPlot, + parameterInfo.numEvents, + samplingMethod); + }); + plotDiv.append(plotButton); + + // Add a selector with the scaling for axis X + var xAxisScalingDiv = xAxisDiv.append($("<div>") + .css("display", "block") + .attr("id", "xAxisScalingDiv")); + xAxisScalingDiv.append($("<label>") + .attr("for", "parameter_form_select_scaleX") + .html("Scale for X axis")); + var selectScaleX = $("<select>") + .css("margin", "0 3px 0 3px") + .attr("id", "parameter_form_select_scaleX"); + xAxisScalingDiv.append(selectScaleX); + + // Add the options + possibleOptions = ["Linear", "Hyperlog"]; + for (i = 0; i < possibleOptions.length; i++) { + selectScaleX.append($("<option>") + .attr("name", possibleOptions[i]) + .attr("value", possibleOptions[i]) + .text(possibleOptions[i])); + } + + // Pre-select "Linear" + $("parameter_form_select_scaleX").val(0); + + // Add a selector with the scaling for axis Y + var yAxisScalingDiv = yAxisDiv.append($("<div>") + .css("display", "block") + .attr("id", "yAxisScalingDiv")); + yAxisScalingDiv.append($("<label>") + .attr("for", "parameter_form_select_scaleY") + .html("Scale for Y axis")); + var selectScaleY = $("<select>") + .css("margin", "0 3px 0 3px") + .attr("id", "parameter_form_select_scaleY"); + yAxisScalingDiv.append(selectScaleY); + + // Add the options + possibleOptions = ["Linear", "Hyperlog"]; + for (i = 0; i < possibleOptions.length; i++) { + selectScaleY.append($("<option>") + .attr("name", possibleOptions[i]) + .attr("value", possibleOptions[i]) + .text(possibleOptions[i])); + } + + // Pre-select "Linear" + $("parameter_form_select_scaleY").val(0); + + // Add a selector with the sampling method + var eventSamplingDiv = eventsDiv.append($("<div>") + .css("display", "block") + .attr("id", "eventSamplingDiv")); + eventSamplingDiv.append($("<label>") + .attr("for", "parameter_form_select_sampling_method") + .html("Sampling")); + var selectSamplingMethod = $("<select>") + .css("margin", "0 3px 0 3px") + .attr("id", "parameter_form_select_sampling_method"); + eventSamplingDiv.append(selectSamplingMethod); + + // Add the options + possibleOptions = ["Regular", "First rows"]; + for (i = 0; i < possibleOptions.length; i++) { + selectSamplingMethod.append($("<option>") + .attr("name", "" + (i + 1)) + .attr("value", (i + 1)) + .text(possibleOptions[i])); + } + + // Pre-select "Linear" + $("parameter_form_select_sampling_method").val(0); + + // + // End of widget + // + + // Append the created div to the container + $container.append(plot_params_div); + + }, + + retrieveParameterInfo: function (model) { + + // Retrieve parameter information + var key = model.dataSetV3.type.code.substring( + 0, model.dataSetV3.type.code.indexOf("_FCSFILE")) + + "_FCSFILE_PARAMETERS"; + + var parametersXML = $.parseXML(model.dataSetV3.properties[key]); + var parameters = parametersXML.childNodes[0]; + + var numParameters = parameters.getAttribute("numParameters"); + var numEvents = parameters.getAttribute("numEvents"); + + var names = []; + var compositeNames = []; + var display = []; + + // Parameter numbering starts at 1 + var parametersToDisplay = 0; + for (var i = 1; i <= numParameters; i++) { + + // If the parameter contains the PnCHANNELTYPE attribute (BD Influx Cell Sorter), + // we only add it if the channel type is 6. + var channelType = parameters.getAttribute("P" + i + "CHANNELTYPE"); + if (channelType != null && channelType !== 6) { + continue; + } + + // Store the parameter name + var name = parameters.getAttribute("P" + i + "N"); + names.push(name); + + // Store the composite name + var pStr = parameters.getAttribute("P" + i + "S"); + var composite = name; + if (pStr !== "") { + composite = name + " (" + pStr + ")"; + } + compositeNames.push(composite); + + // Store the display scale + var displ = parameters.getAttribute("P" + i + "DISPLAY"); + display.push(displ); + + // Update the count of parameters to display + parametersToDisplay++; + } + + // Store the parameter info + parameterInfo = { + "numParameters": parametersToDisplay, + "numEvents": numEvents, + "names": names, + "compositeNames": compositeNames, + "display": display + }; + + // Return it + return parameterInfo; + }, + + callServerSidePluginGenerateFCSPlot: function (model, paramX, paramY, displayX, displayY, numEventsToPlot, totalNumEvents, samplingMethod) { + + // Check whether the data for the plot is already cached + var key = model.dataSetV3.code + "_" + paramX + "_" + paramY + "_" + numEventsToPlot.toString() + + "_" + displayX + "_" + displayY + "_" + samplingMethod.toString(); + + if (model.dataSetV3.code in this.dataCache && + key in this.dataCache[model.dataSetV3.code]) { + + // Plot the cached data + this.plotFCSData( + this.dataCache[model.dataSetV3.code][key], + paramX, + paramY, + displayX, + displayY); + + // Return immediately + return; + } + + // Inform the user that we are about to process the request + this.displayStatus("Please wait while processing your request. This might take a while...", + "info"); + + var thisObj = this; + require(["openbis", + "as/dto/service/search/AggregationServiceSearchCriteria", + "as/dto/service/fetchoptions/AggregationServiceFetchOptions", + "as/dto/service/execute/AggregationServiceExecutionOptions"], + function (openbis, + AggregationServiceSearchCriteria, + AggregationServiceFetchOptions, + AggregationServiceExecutionOptions) { + + // Parameters for the aggregation service + var options = new AggregationServiceExecutionOptions(); + options.withParameter("code", model.dataSetV3.code); + options.withParameter("paramX", paramX); + options.withParameter("paramY", paramY); + options.withParameter("displayX", displayX); + options.withParameter("displayY", displayY); + options.withParameter("numEvents", totalNumEvents); + options.withParameter("maxNumEvents", numEventsToPlot); + options.withParameter("samplingMethod", samplingMethod); + options.withParameter("nodeKey", model.dataSetV3.code); + + // Call service + if (null === thisObj.retrieveFCSEventsService) { + var criteria = new AggregationServiceSearchCriteria(); + criteria.withName().thatEquals("retrieve_fcs_events"); + var fetchOptions = new AggregationServiceFetchOptions(); + mainController.openbisV3.searchAggregationServices(criteria, fetchOptions).then(function (result) { + + // Check that we got our service + if (undefined === result.objects) { + console.log("Could not retrieve the server-side aggregation service!"); + return; + } + thisObj.retrieveFCSEventsService = result.getObjects()[0]; + + // Now call the service + mainController.openbisV3.executeAggregationService( + thisObj.retrieveFCSEventsService.getPermId(), + options).then(function (result) { + thisObj.processResultsFromRetrieveFCSEventsServerSidePlugin(result); + }); + }); + } else { + // Call the service + mainController.openbisV3.executeAggregationService( + thisObj.retrieveFCSEventsService.getPermId(), + options).then(function (result) { + thisObj.processResultsFromRetrieveFCSEventsServerSidePlugin(result); + }); + } + }); + }, + + plotFCSData: function (data, xLabel, yLabel, xDisplay, yDisplay) { + + // Make sure to have a proper array + var parsed_data = JSON.parse(data); + + // Prepend data names to be compatible with C3.js + parsed_data[0].unshift("x_values"); + parsed_data[1].unshift("y_values"); + + // Plot the data + c3.generate({ + bindto: '#plot_canvas_div', + title: { + text: yLabel + " vs. " + xLabel + }, + data: { + xs: { + y_values: "x_values" + }, + columns: [ + parsed_data[0], + parsed_data[1], + ], + names: { + y_values: yLabel + }, + type: 'scatter' + }, + axis: { + x: { + label: xLabel, + tick: { + fit: false + } + }, + y: { + label: yLabel, + tick: { + fit: false + } + } + }, + legend: { + show: false + }, + tooltip: { + format: { + title: function (d) { + const format = d3.format(','); + return xLabel + " | " + format(d); + }, + value: function (value, ratio, id) { + const format = d3.format(','); + return format(value); + } + } + }, + zoom: { + enabled: true, + rescale: true + }, + }); + }, + + processResultsFromRetrieveFCSEventsServerSidePlugin: function (table) { + + // Did we get the expected result? + if (!table.rows || table.rows.length !== 1) { + DATAVIEWER.displayStatus( + "There was an error retrieving the data to plot!", + "danger"); + return; + } + + // Get the row of results + var row = table.rows[0]; + + // Retrieve the uid + var r_UID = row[0].value; + + // Is the process completed? + var r_Completed = row[1].value; + + var thisObj = this; + if (r_Completed === 0) { + + require(["as/dto/service/execute/AggregationServiceExecutionOptions"], + function (AggregationServiceExecutionOptions) { + + // Call the plug-in + setTimeout(function () { + + // Now call the service again: + // we only need the UID of the job + var options = new AggregationServiceExecutionOptions(); + options.withParameter("uid", r_UID); + + mainController.openbisV3.executeAggregationService( + thisObj.retrieveFCSEventsService.getPermId(), + options).then(function (result) { + thisObj.processResultsFromRetrieveFCSEventsServerSidePlugin(result); + }) + }, 2000); + }); + + // Return here + return; + + } + + // We completed the call and we can process the result + + // Returned parameters + var r_Success = row[2].value; + var r_ErrorMessage = row[3].value; + var r_Data = row[4].value; + var r_Code = row[5].value; + var r_ParamX = row[6].value; + var r_ParamY = row[7].value; + var r_DisplayX = row[8].value; + var r_DisplayY = row[9].value; + var r_NumEvents = row[10].value; // Currently not used + var r_MaxNumEvents = row[11].value; + var r_SamplingMethod = row[12].value; + var r_NodeKey = row[13].value; + + var level; + if (r_Success === 1) { + + // Error message and level + status = r_ErrorMessage; + level = "success"; + + // Plot the data + thisObj.plotFCSData(r_Data, r_ParamX, r_ParamY, r_DisplayX, r_DisplayY); + + // Cache the plotted data + var dataKey = r_Code + "_" + r_ParamX + "_" + r_ParamY + "_" + r_MaxNumEvents.toString() + + "_" + r_DisplayX + "_" + r_DisplayY + "_" + r_SamplingMethod.toString(); + thisObj.cacheFCSData(r_NodeKey, dataKey, r_Data); + + } else { + status = "Sorry, there was an error: \"" + r_ErrorMessage + "\"."; + level = "danger"; + } + + // We only display errors + if (r_Success === 0) { + thisObj.displayStatus(status, level); + } else { + thisObj.hideStatus(); + } + + return table; + + }, + + cacheFCSData: function (nodeKey, dataKey, fcsData) { + + // Cache the data + if (! (nodeKey in this.dataCache)) { + this.dataCache[nodeKey] = {}; + } + this.dataCache[nodeKey][dataKey] = fcsData; + }, + + displayStatus: function(status, level) { + switch (level) { + case "info": + color = "black"; + break; + case "success": + color = "cyan"; + break; + case "danger": + color = "red"; + break; + default: + color = "black"; + break; + } + var status_div = $("#status_div"); + status_div + .css("color", color) + .text(status); + status_div.show(); + }, + + hideStatus: function() { + $("#status_div").hide(); + } }); diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/MicroscopyTechnology.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/MicroscopyTechnology.js index 5ee6177db2a6e8d3c46c8503a850f9518e1f9b57..4b07aee2df65149b57fda977646e35c66b870295 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/MicroscopyTechnology.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/plugins/MicroscopyTechnology.js @@ -14,14 +14,14 @@ $.extend(MicroscopyTechnology.prototype, ELNLIMSPlugin.prototype, { "SHOW": false, "SAMPLE_CHILDREN_DISABLED": true, "SAMPLE_PARENTS_DISABLED": true, - "TOOLBAR": { CREATE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true } + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true } }, "MICROSCOPY_EXPERIMENT": { "SHOW": false, "SAMPLE_CHILDREN_DISABLED": false, "SAMPLE_PARENTS_DISABLED": false, "SAMPLE_PARENTS_ANY_TYPE_DISABLED": true, - "TOOLBAR": { CREATE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, + "TOOLBAR": { CREATE: false, FREEZE: false, EDIT: true, MOVE: false, COPY: false, DELETE: false, PRINT: true, HIERARCHY_GRAPH: true, HIERARCHY_TABLE: true, UPLOAD_DATASET: false, UPLOAD_DATASET_HELPER: false, EXPORT_ALL: true, EXPORT_METADATA: true }, "SAMPLE_PARENTS_HINT": [{ "LABEL": "Organization Units", "TYPE": "ORGANIZATION_UNIT", @@ -32,23 +32,23 @@ $.extend(MicroscopyTechnology.prototype, ELNLIMSPlugin.prototype, { dataSetTypeDefinitionsExtension: { "MICROSCOPY_ACCESSORY_FILE": { "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: true, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } }, "MICROSCOPY_IMG": { "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: true, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } }, "MICROSCOPY_IMG_OVERVIEW": { "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: true, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } }, "MICROSCOPY_IMG_THUMBNAIL": { "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: true, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } }, "MICROSCOPY_IMG_CONTAINER": { "DATASET_PARENTS_DISABLED": true, - "TOOLBAR": { EDIT: true, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } + "TOOLBAR": { EDIT: false, FREEZE: false, MOVE: false, ARCHIVE: true, DELETE: false, HIERARCHY_TABLE: true, EXPORT_ALL: true, EXPORT_METADATA: true } } }, sampleFormTop: function ($container, model) { diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js index 4f792823e08c42ef84feec074522bc4ffcb232aa..d07f3dbe6015efe3485d2b319264c13248041baf 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/server/ServerFacade.js @@ -1442,6 +1442,7 @@ function ServerFacade(openbisServer) { v1Sample["permId"] = (v3Sample.permId)?v3Sample.permId.permId:null; v1Sample["code"] = v3Sample.code; v1Sample["identifier"] = (v3Sample.identifier)?v3Sample.identifier.identifier:null; + v1Sample["projectCode"] = (v3Sample.project) ? v3Sample.project.code : null; v1Sample["experimentIdentifierOrNull"] = (v3Sample.experiment)?v3Sample.experiment.identifier.identifier:null; v1Sample["sampleTypeCode"] = (v3Sample.type)?v3Sample.type.code:null; v1Sample["properties"] = v3Sample.properties; @@ -1789,6 +1790,7 @@ function ServerFacade(openbisServer) { fetchOptions.withType(); fetchOptions.withRegistrator(); fetchOptions.withModifier(); + fetchOptions.withProject(); fetchOptions.withExperiment(); if(fechOptions["withProperties"]) { fetchOptions.withProperties(); diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js index 3a069f65163f5434f0c6b13e733b40a0c460d73e..0f19fad800668acdbcce3b9188a6908222b498d3 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/util/FormUtil.js @@ -632,7 +632,18 @@ var FormUtil = new function() { } } + this.createPropertyField = function(propertyType, propertyValue) { + if (propertyType.dataType === "CONTROLLEDVOCABULARY") { + propertyValue = this.getVocabularyLabelForTermCode(propertyType, propertyValue); + } + return this._createField(propertyType.dataType === "HYPERLINK", propertyType.label, propertyValue, propertyType.code); + } + this.getFieldForLabelWithText = function(label, text, id, postComponent, cssForText) { + return this._createField(false, label, text, id, postComponent, cssForText); + } + + this._createField = function(hyperlink, label, text, id, postComponent, cssForText) { var $fieldset = $('<div>'); var $controlGroup = $('<div>', {class : 'form-group'}); @@ -660,7 +671,8 @@ var FormUtil = new function() { if(text) { text = text.replace(/(?:\r\n|\r|\n)/g, '\n'); //Normalise carriage returns } - $component.html(html.sanitize(text)); + text = html.sanitize(text); + $component.html(hyperlink ? this.asHyperlink(text) : text); if(id) { $component.attr('id', id); @@ -669,6 +681,10 @@ var FormUtil = new function() { return $fieldset; } + + this.asHyperlink = function(text) { + return $("<a>", { "href" : text, "target" : "_blank"}).append(text); + } // // Get Field from property diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/ExperimentDataGridUtil.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/ExperimentDataGridUtil.js index 5d730a9a2bc39bd66bd587386772c9c94e97ecd2..39e5d47cbbd2ab80a66e0dd5ec5f42b44f0edead 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/ExperimentDataGridUtil.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/ExperimentDataGridUtil.js @@ -79,6 +79,19 @@ var ExperimentDataGridUtil = new function() { var newVocabularyColumnFunc = getVocabularyColumn(propertyType); propertyColumnsToSort.push(newVocabularyColumnFunc()); + } else if (propertyType.dataType === "HYPERLINK") { + var getHyperlinkColumn = function(propertyType) { + return { + label : propertyType.label, + property : propertyType.code, + isExportable: true, + sortable : true, + render : function(data) { + return FormUtil.asHyperlink(data[propertyType.code]); + } + }; + } + propertyColumnsToSort.push(getHyperlinkColumn(propertyType)); } else { propertyColumnsToSort.push({ label : propertyCodesDisplayNames[idx], diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/SampleDataGridUtil.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/SampleDataGridUtil.js index 5330e2396df1d6a2289a2c53ee95a81e5c1e2918..90e4cef2d10a5b9e9853ff1391b48c52c18d3240 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/SampleDataGridUtil.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataGrid/SampleDataGridUtil.js @@ -289,6 +289,19 @@ var SampleDataGridUtil = new function() { var newVocabularyColumnFunc = getVocabularyColumn(propertyType); propertyColumnsToSort.push(newVocabularyColumnFunc()); + } else if (propertyType.dataType === "HYPERLINK") { + var getHyperlinkColumn = function(propertyType) { + return { + label : propertyType.label, + property : propertyType.code, + isExportable: true, + sortable : true, + render : function(data) { + return FormUtil.asHyperlink(data[propertyType.code]); + } + }; + } + propertyColumnsToSort.push(getHyperlinkColumn(propertyType)); } else { propertyColumnsToSort.push({ label : propertyType.label, diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataSetForm/DataSetFormView.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataSetForm/DataSetFormView.js index 4c7e7dec799b9e9e7d3eb5fcc839b4d70d32fbd4..16305c02188adc0f4465e31c31d62673e7c5d1dc 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataSetForm/DataSetFormView.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/DataSetForm/DataSetFormView.js @@ -650,10 +650,7 @@ function DataSetFormView(dataSetFormController, dataSetFormModel) { if(this._dataSetFormModel.mode === FormMode.VIEW) { if(Util.getEmptyIfNull(value) !== "") { //Don't show empty fields, whole empty sections will show the title - if(propertyType.dataType === "CONTROLLEDVOCABULARY") { - value = FormUtil.getVocabularyLabelForTermCode(propertyType, value); - } - var $controlGroup = FormUtil.getFieldForLabelWithText(propertyType.label, value, propertyType.code); + $controlGroup = FormUtil.createPropertyField(propertyType, value); $fieldset.append($controlGroup); } else { continue; diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/ExperimentForm/ExperimentFormView.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/ExperimentForm/ExperimentFormView.js index babba314421db26fa10cce73a487431d024c75cb..5c2958f79f05f741f8f035c2ad23d4dbfea8043a 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/ExperimentForm/ExperimentFormView.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/ExperimentForm/ExperimentFormView.js @@ -421,10 +421,7 @@ function ExperimentFormView(experimentFormController, experimentFormModel) { if(this._experimentFormModel.mode === FormMode.VIEW) { //Show values without input boxes if the form is in view mode if(Util.getEmptyIfNull(value) !== "") { //Don't show empty fields, whole empty sections will show the title - if(propertyType.dataType === "CONTROLLEDVOCABULARY") { - value = FormUtil.getVocabularyLabelForTermCode(propertyType, value); - } - $controlGroup = FormUtil.getFieldForLabelWithText(propertyType.label, value); + $controlGroup = FormUtil.createPropertyField(propertyType, value); } else { continue; } diff --git a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js index 812b8d51f7e01cd0d09642ea2aca34717aba3413..b7bc8398bd3e7ed8f0a5892d68eb065852f22abb 100644 --- a/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js +++ b/openbis_standard_technologies/dist/core-plugins/eln-lims/1/as/webapps/eln-lims/html/js/views/SampleForm/SampleFormView.js @@ -658,10 +658,7 @@ function SampleFormView(sampleFormController, sampleFormModel) { if(this._sampleFormModel.mode === FormMode.VIEW) { //Show values without input boxes if the form is in view mode if(Util.getEmptyIfNull(value) !== "") { //Don't show empty fields, whole empty sections will show the title - if(propertyType.dataType === "CONTROLLEDVOCABULARY") { - value = FormUtil.getVocabularyLabelForTermCode(propertyType, value); - } - $controlGroup = FormUtil.getFieldForLabelWithText(propertyType.label, value, propertyType.code); + $controlGroup = FormUtil.createPropertyField(propertyType, value); } else { continue; }