Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
19d6d77
Sample listing grid updates to include ExpMaterialColor and use SAMPL…
cnathe Jul 31, 2026
77a461d
ExperimentService getActiveProjectColors()
cnathe Jul 31, 2026
3a37f3c
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Jul 31, 2026
a7e4fb4
remove experimental feature flag
cnathe Jul 31, 2026
d73fd47
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 4, 2026
3b059e9
ExperimentService getDataColorLabel -> getDataColor
cnathe Aug 5, 2026
5071ed3
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 6, 2026
b451b4e
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 10, 2026
6178864
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 12, 2026
d8a831d
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 12, 2026
2054382
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 13, 2026
195648f
remove todos
cnathe Aug 13, 2026
10f748a
ExperimentService getAllProjectColors()
cnathe Aug 13, 2026
90303f7
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 14, 2026
7436531
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 17, 2026
e9d42d2
DataColorTable to show Container column, initially hidden
cnathe Aug 17, 2026
e073d29
Add isMedia check to colorsEnabled
cnathe Aug 17, 2026
18459f7
Merge remote-tracking branch 'origin/develop' into fb_sampleColor2
cnathe Aug 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion api/src/org/labkey/api/audit/SampleTimelineAuditEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import org.jetbrains.annotations.Nullable;
import org.labkey.api.collections.CaseInsensitiveHashMap;
import org.labkey.api.data.Container;
import org.labkey.api.exp.api.DataColor;
import org.labkey.api.exp.api.ExperimentService;
import org.labkey.api.qc.DataState;
import org.labkey.api.qc.SampleStatusService;
Expand Down Expand Up @@ -278,7 +279,11 @@ private String getColorLabel(Map<String, String> row, Container container)
{
String value = row.get(ExpMaterialColor.name());
if (!StringUtils.isBlank(value))
return ExperimentService.get().getDataColorLabel(container, Long.parseLong(value));
{
DataColor dataColor = ExperimentService.get().getDataColor(container, Long.parseLong(value));
if (dataColor != null)
return dataColor.getLabel();
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
* Licensed under the Apache License, Version 2.0: http://www.apache.org/licenses/LICENSE-2.0
*/
package org.labkey.experiment.api;
package org.labkey.api.exp.api;

import org.labkey.api.data.Container;
import org.labkey.api.data.Entity;
Expand Down
8 changes: 5 additions & 3 deletions api/src/org/labkey/api/exp/api/ExperimentService.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,6 @@ public interface ExperimentService extends ExperimentRunTypeSource

String EXPERIMENTAL_FEATURE_ALLOW_ROW_ID_MERGE = "org.labkey.experiment.api.SampleTypeUpdateServiceDI#ALLOW_ROW_ID_SAMPLE_MERGE";

String EXPERIMENTAL_SAMPLE_COLORS = "org.labkey.api.exp.api.ExperimentService#SAMPLE_COLORS";

int SIMPLE_PROTOCOL_FIRST_STEP_SEQUENCE = 1;
int SIMPLE_PROTOCOL_CORE_STEP_SEQUENCE = 10;
int SIMPLE_PROTOCOL_EXTRA_STEP_SEQUENCE = 15;
Expand Down Expand Up @@ -1160,7 +1158,11 @@ List<? extends ExpProtocol> getExpProtocolsWithParameterValue(

@NotNull Set<Long> getActiveDataTypeColors(@NotNull Container container, DataTypeForExclusion dataType, long dataTypeId);

@Nullable String getDataColorLabel(@NotNull Container container, long colorRowId);
@NotNull List<DataColor> getActiveProjectColors(@NotNull Container container);

@NotNull List<DataColor> getAllProjectColors(@NotNull Container container);

@Nullable DataColor getDataColor(@NotNull Container container, long colorRowId);

boolean ensureDataColorExclusions(long dataTypeId, DataTypeForExclusion dataType, @Nullable Collection<Long> disabledColorRowIds, @NotNull Container container, User user);

Expand Down
2 changes: 1 addition & 1 deletion experiment/src/org/labkey/experiment/ExpDataIterators.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@
import org.labkey.experiment.api.ExpMaterialTableImpl;
import org.labkey.experiment.api.ExpRunItemTableImpl;
import org.labkey.experiment.api.ExpSampleTypeImpl;
import org.labkey.experiment.api.DataColor;
import org.labkey.api.exp.api.DataColor;
import org.labkey.experiment.api.DataColorManager;
import org.labkey.experiment.api.ExperimentServiceImpl;
import org.labkey.experiment.api.SampleTypeServiceImpl;
Expand Down
3 changes: 0 additions & 3 deletions experiment/src/org/labkey/experiment/ExperimentModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,6 @@ protected void init()
"Support for querying lineage of experiment objects", false, true);
OptionalFeatureService.get().addExperimentalFeatureFlag(ExperimentService.EXPERIMENTAL_FEATURE_ALLOW_ROW_ID_MERGE, "Allow RowId to be accepted when merging samples or data class data",
"If the incoming data includes a RowId column we will allow the column but ignore it's values.", false, true);
OptionalFeatureService.get().addExperimentalFeatureFlag(ExperimentService.EXPERIMENTAL_SAMPLE_COLORS, "Sample Colors",
"Enable assigning custom colors to individual samples, with an app-level color palette configurable per sample type.", false, true);

RoleManager.registerPermission(new DesignVocabularyPermission(), true);
RoleManager.registerRole(new SampleTypeDesignerRole());
Expand Down Expand Up @@ -1241,7 +1239,6 @@ public JSONObject getPageContextJson(ContainerUser context)
{
JSONObject json = super.getPageContextJson(context);
json.put(SAMPLE_FILES_TABLE, OptionalFeatureService.get().isFeatureEnabled(SAMPLE_FILES_TABLE));
json.put("SampleColors", OptionalFeatureService.get().isFeatureEnabled(ExperimentService.EXPERIMENTAL_SAMPLE_COLORS));
return json;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.labkey.api.data.SimpleFilter;
import org.labkey.api.data.Sort;
import org.labkey.api.data.TableSelector;
import org.labkey.api.exp.api.DataColor;

import java.util.ArrayList;
import java.util.Collections;
Expand Down Expand Up @@ -91,12 +92,6 @@ public List<DataColor> getColors(Container container)
return CACHE.get(container)._colors;
}

@NotNull
public List<DataColor> getActiveColors(Container container)
{
return getColors(container).stream().filter(c -> !c.isArchived()).toList();
}

@NotNull
public List<DataColor> getAllProjectColors(Container container)
{
Expand Down
5 changes: 2 additions & 3 deletions experiment/src/org/labkey/experiment/api/DataColorTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import org.labkey.api.data.SqlSelector;
import org.labkey.api.data.TableInfo;
import org.labkey.api.data.TableSelector;
import org.labkey.api.exp.api.DataColor;
import org.labkey.api.exp.api.ExpMaterial;
import org.labkey.api.exp.api.ExpSampleType;
import org.labkey.api.exp.api.ExperimentService;
Expand Down Expand Up @@ -72,10 +73,8 @@ public DataColorTable(ExpSchema schema, ContainerFilter cf)
for (ColumnInfo baseColumn : _rootTable.getColumns())
{
String name = baseColumn.getName();
if ("Container".equalsIgnoreCase(name))
continue;
var col = addWrapColumn(baseColumn);
if ("RowId".equalsIgnoreCase(name))
if ("RowId".equalsIgnoreCase(baseColumn.getName()) || "Container".equalsIgnoreCase(name))
col.setHidden(true);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@
import org.labkey.api.security.permissions.Permission;
import org.labkey.api.security.permissions.ReadPermission;
import org.labkey.api.security.permissions.UpdatePermission;
import org.labkey.api.settings.OptionalFeatureService;
import org.labkey.api.test.TestWhen;
import org.labkey.api.util.ContextListener;
import org.labkey.api.util.GUID;
Expand Down Expand Up @@ -774,9 +773,7 @@ private static boolean isStatusEnabled(Container c)

private boolean colorsEnabled(Container c)
{
if (!OptionalFeatureService.get().isFeatureEnabled(ExperimentService.EXPERIMENTAL_SAMPLE_COLORS))
return false;
if (_ss != null)
if (_ss != null && !_ss.isMedia())
return !ExperimentService.get().getActiveDataTypeColors(c, ExperimentService.DataTypeForExclusion.SampleType, _ss.getRowId()).isEmpty();
return !DataColorManager.getInstance().getActiveProjectColors(c).isEmpty();
}
Expand Down Expand Up @@ -867,6 +864,9 @@ protected void populateColumns()
addColumn(SampleSet);
addColumn(MaterialExpDate);
defaultCols.add(MaterialExpDate.fieldKey());
addColumn(ExpMaterialColor);
if (colorsEnabled(getContainer()))
defaultCols.add(ExpMaterialColor.fieldKey());
addContainerColumn(Folder, null);
if (getContainer().hasProductFolders())
defaultCols.add(Folder.fieldKey());
Expand All @@ -886,9 +886,6 @@ protected void populateColumns()
addColumn(SampleState);
if (isStatusEnabled(getContainer()))
defaultCols.add(SampleState.fieldKey());
addColumn(ExpMaterialColor);
if (colorsEnabled(getContainer()))
defaultCols.add(ExpMaterialColor.fieldKey());

// TODO is this a real Domain???
if (st != null && !"urn:lsid:labkey.com:SampleSource:Default".equals(st.getDomain().getTypeURI()))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
import org.labkey.api.exp.XarSource;
import org.labkey.api.exp.api.ColumnExporter;
import org.labkey.api.exp.api.DataClassDomainKindProperties;
import org.labkey.api.exp.api.DataColor;
import org.labkey.api.exp.api.DataType;
import org.labkey.api.exp.api.ExpData;
import org.labkey.api.exp.api.ExpDataClass;
Expand Down Expand Up @@ -9186,11 +9187,10 @@ public String getDisabledDataTypeAuditMsg(DataTypeForExclusion type, List<Long>
}

@Override
public @Nullable String getDataColorLabel(@NotNull Container container, long colorRowId)
public @Nullable DataColor getDataColor(@NotNull Container container, long colorRowId)
{
return DataColorManager.getInstance().getAllProjectColors(container).stream()
return getAllProjectColors(container).stream()
.filter(c -> c.getRowId() == colorRowId)
.map(DataColor::getLabel)
.findFirst()
.orElse(null);
}
Expand All @@ -9205,6 +9205,18 @@ public String getDisabledDataTypeAuditMsg(DataTypeForExclusion type, List<Long>
.collect(toSet());
}

@Override
public @NotNull List<DataColor> getActiveProjectColors(@NotNull Container container)
{
return DataColorManager.getInstance().getActiveProjectColors(container);
}

@Override
public @NotNull List<DataColor> getAllProjectColors(@NotNull Container container)
{
return DataColorManager.getInstance().getAllProjectColors(container);
}

// Applies a reconciled set of exclusion changes to exp.DataTypeColorExclusion in one transaction: one key column is
// held fixed (fixedColumn = fixedValue), the other varies. Rows in toAdd are inserted; rows in toRemove are deleted.
// Shared by ensureDataColorExclusions (fixes DataTypeRowId, varies ColorRowId) and updateColorDataTypeExclusions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7749,6 +7749,7 @@ private SQLFragment getOrderedRowsSql()
sampleColumns.addAll(Arrays.asList(
"S.Name AS SampleID",
"S.MaterialExpDate AS ExpirationDate",
"S.ExpMaterialColor",
"S.SampleSet as SampleType",
"S.SampleState",
"S.isAliquot",
Expand All @@ -7761,6 +7762,7 @@ private SQLFragment getOrderedRowsSql()
sampleColumns.addAll(Arrays.asList(
"S.Name AS SampleID",
"S.MaterialExpDate AS ExpirationDate",
"S.ExpMaterialColor",
"S.LabelColor",
"S.SampleSet",
"S.SampleState",
Expand Down
3 changes: 2 additions & 1 deletion list/src/org/labkey/list/model/ListTable.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,10 @@ public class ListTable extends FilteredTable<ListQuerySchema> implements Updatea
{
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "Name"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "MaterialExpDate"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "ExpMaterialColor"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "LabelColor"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "Folder"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "SampleSet"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "Folder"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "SampleState"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "StoredAmount"));
defaultPicklistVisibleColumns.add(FieldKey.fromParts(PICKLIST_SAMPLE_ID, "Units"));
Expand Down